백만 데이터 <처리> SQL 문을 최적화의 양

A : 이해 SQL의 실행 순서

        에서 SQL , 첫 번째 수행되는 에서 문, 다음 단계에 대한 쿼리가 같은 문으로 할 때 가상 테이블을 생성 각 단계는, 테이블이 호출됩니다 사용자 WHERE에서, 컬럼 10, colum2, 최대 (3 열)을 선택 컬럼 1에 의해 ID> 1 기 colum2 갖는 카운트 (컬럼 1)> 1 개 colum2 순서.

      SQLSERVER 2005 간단한의 모든 측면 :

 

( 8 )를 선택 ( 9 ) DISTINCT   ( 11 ) <톱 민> <선택리스트>

( 1 ) FROM [left_table]

( 3 ) <join_type> 가입 <right_table>

( 2 ) ON <join_condition>

( 4 ) 여기서 <where_condition>

( 5 ) GROUP BY <group_by_list>

( 6 ) <큐브 | 롤업>

( 7 )를 갖는 <having_condition>

( 10 BY) ORDER <order_by_list>

 

   A) 단계의 소개 :

  1. FROM 다음에 FROM 실행 테이블 다수의 직교 제품의 절 ( 직교 제품의) ( 크로스 커플 링), 가상 테이블 생성 VT1을
  2. ON : 대한 VT1의 응용 프로그램 ON 필터. 만하는 사람들 <join_condition> 본선은 삽입 된 VT2을 .
  3. OUTER (조인) :로 지정된 경우 아우터 가입 (상대 CROSS JOIN 또는 (내부 조인), 예약 표 ( 브드 표 : LEFT OUTER 왼쪽 테이블 예약 테이블로 표시 JOIN 오른쪽 외부 조인 오른쪽 테이블 예약 테이블로 표시된 완전 외부 두 테이블 매치 외부 로우 행에 추가로 발견된다) 예약 테이블로 표시된 가입 , VT2 생성 VT3있다. 경우] FROM 절 두 개 이상의 테이블을 포함하는 커플 링 결과 테이블에 생성되고 다음 테이블의 단계를 반복하여 1 단계 3을 완전히 처리하는 모든 테이블까지.
  4. WHERE : 대한 VT3의 응용 프로그램 WHERE 필터. 만 때 <where_condition> 입니다 진정한 라인은 삽입 된 VT4합니다.
  5. BY GROUP 보도 : BY GROUP 절 열 목록 VT4의 행 패킷 생성 VT5을.
  6. CUBE | ROLLUP : 슈퍼 그룹 (Suppergroups)이 삽입 VT5를 생성 VT6을.
  7. HAVING :에 VT6의 응용 프로그램 HAVING 필터. 만 때 <having_condition> 입니다 진정한 그룹이 삽입됩니다 VT7합니다.
  8. SELECT : 처리 SELECT 리스트를 초래 VT8.
  9. 별개 : 중복 행 VT8은 결과, 제거 VT9.
  10. ORDER에 의해 다음 VT9에 의해 행 BY ORDER 정렬 된 열 목록 절, 커서 (생성 VClO을).
  11. 정상은 :부터 VC10 수 또는 라인 생성 테이블의 시작의 비율을 지정하는 선택 VT11를 호출자에게 반환을 .

 

  b) 표준 SQL의 실행 순서이다 :

  1 형태 예와 같은 다른 테이블, 데이터의 어셈블리 형태로 사용자 또는 U AS는 AS goodsOrder 가입 양식 사용자 = R & LT ON u.id r.userid

  2 곳 과 같은 검색 기준에 맞는 필터링 데이터 : ID> 1,000

  3 : 그룹화 그룹 데이터에 대한 쿼리

  4 : 사용 금액을 집계 함수가 계산처럼.

  5 : 사용이 필요 상영 그룹.

  6 : 실행 선택 언어를

  7 : 정렬 문을 수행

  如: 선택 카운트 (GID) shopping_goods에서 gname는 gname는 카운트를 갖는 (GID)> 카운트 (GID) DESC 1 명 ORDER BY gcid = 1 기

  1 : 홈 질의 shopping_goods 테이블은 테이블의 데이터를 얻을 수

  2 : 실행 , 여과 gcid = 1 개 제품.

  3 : 에 대한 gname는의 그룹.

  4:使用聚合函数count(),计算出商品类型为1,不同商品名称的数量.

  5:使用having,过滤出类型为1,商品统计数量大于1的商品

  6:执行select语句

  7:执行order by ,按照商品数量降序排列。

二:百万数据量优化

  这里只介绍查询和修改的方法,如果是系统优化,需要从表结构,索引,表分区等方面处理。

  1:合理使用索引,在一个大数据量的表中,并不是索引越多越好,索引越多,写操作越慢,建议在以下字段上创建索引。

  在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引。

  在频繁进行排序或分组(即进行group byorder by操作)的列上建立索引。

  在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的性别列上只有两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。

  如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。

  使用系统工具。如Informix数据库有一个tbcheck工具,可以在可疑的索引上进行检查。在一些数据库服务器上,索引可能失效或者因为频繁操作而使得读取效率降低,如果一个使用索引的查询不明不白地慢下来,可以试着用tbcheck工具检查索引的完整性,必要时进行修复。另外,当数据库表更新大量数据后,删除并重建索引可以提高查询速度。

  2:尽量少用(或者不用)sqlserver 自带的函数

  a):dateadd(month,-1,getdate()),请使用time>'2017-09-19 23:42:44.770 '代替dateadd.

  b):datediff(day,'2017-10-20','2017-10-25'),select datepart(day,getdate());,如需计算两个日期之前的差值,或者得到日期中的整数部分,建议查询完毕后用java程序来计算,不要什么都让数据库来做.

  c:) 如:substring(name,1,3) = ’abc’,建议修改为 name like 'abc%'

 

  3:尽量不要在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,强烈建议where涉及的列,不要留空,创建表时赋予初始值

错误
select id from table where name is not null
正确
create table table(name varchar(20) default '')

   4:应尽量避免在 where 子句中使用 != <> 操作符,否则将引擎放弃使用索引而进行全表扫描。

   

错误

select id from table where id <> 100 

  5:应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,建议使用unall 来代替or

  

select id from table where num=1 or Name = 'zhangsan'

建议修改为

select id from table where num=1 

unionall 

select id from table where  name = 'zhangsan'

  6:建议使用exists 来代替in,能用between 就不要使用in 如:age in (20,21,22)建议修改为:age between 20 and 22

  
select id from t where role in (select rid from role where rName = '经理')

建议修改为

select id from t as a where exists (select rid from role  as b where a.role  = b.rid and rName = '经理')

  7:like 的用法

  除了 title  like '重庆%' ,其它使用方法(如:title like  '%%' title like '%')也将导致全表扫描

    8:where 中尽量不要出现表达式计算

  如:

select id from t where num/2 = 100

  应改为:

select id from t where num = 100*2

  9:Update 语句,如果只更改12个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。强烈建议修改时使用动态sql语句,类似hibernatedynamic-update=true,不过hibernate需要将修改对像通过id查询出来,才会动态修改,如果是普通sql,直接组装就可以。

  10:对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差.

  11:不要写一些没有意义的查询,如需要生成一个空表结构:

select col1,col2 into #t from t where 1=0

 

  12:尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连 接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

  13:尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

  14:不建议使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

  15:尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。

  16:在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

  17:尽量避免大事务操作,提高系统并发能力。并且不要事务嵌套,不要在事务中去调用其它系统的接口,不要在事务中耗时操作,不然死锁并伴你左右

  18:尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。(笔者曾经处理过,从3000万手机号码库中,模糊查询出上万个手机号码,这种需求是客户硬性要求,就要通过executorservice了,不要直接写sql)

19:如果数据库是mysql,一定要利用数据库引擎,不同业务要使用不同的数据库引擎。比如常用的innodbmyisam,innodb支持事务,支持外键,锁是表级锁,缺点是查询速度慢,Myisam 的执行速度更快,性能更好,但不支持外键,不支持事务,锁是行锁级。比如日志表,数据量大,强烈建议使用myisam引擎.

추천

출처www.cnblogs.com/bugo/p/10994424.html