sql优化

一、sql 查询主要耗时阶段

    1、where 子句筛选数据
    2、数据库 I/O
    3、返回数据
    注:返回的数据量与I/O其实是同一个问题
 

二、sql 优化之索引

   1、索引的种类

       1、B-tree 索引(实际就是二叉树)

            特点:1、指针定义了子节点页中值的上限和下限。
                       2、该索引按顺序组织存储,很适合范围查找。
            适合的查询:1、全键值、键值范围、键前缀查找。
                                  2、该索引除了满足按值查找操作。还可以用于查询中的order by子句。
            索引的限制:1、不是按照索引左列开始查找则无法使用索引。
                                 2、不能跳过索引中的列进行查找。
                                 3、查询中某个列是范围查询,则其右侧所有列无法使用索引。
                                 注:该限制主要针对复合索引的限制

       2、哈希索引

   2、索引的优点

       1、大大减少需要扫描的数据量
       2、可以避免排序和临时表
       3、可以将随机I/O变为顺序I/O

   3、高效使用索引

       1、无法使用索引的情况

         1、查询中的列必须是独立的列。即列不能是表达式的一部分,不能是函数的参数,不能含有隐式转换  
 1     # 列是表达式的一部分
 2     select * 
 3     from application as a 
 4     where a.id + 1 = 5000 
5 # 列是函数的参数 6 select * 7 from application as a 8 where date(a.created_at) = '20181010' 9 10 # 含有隐式转换(user_id 为int类型) 11 select * 12 from application as a 13 where a.user_id = '567'    
         2、like查询是以通配符开头的(like '%a%')
1      select *
2      from application as a
3      where a.name = '%xia%'
4      注:以上不能使用索引针对单列索引。对于复合索引,索引中对应列前面的列依旧可以使用索引。

       2、多列复合索引的使用条件

         1、必须符合最左前缀要求    

 1     # 现有复合索引 cycle、sex、status
 2  
 3     select *
 4     from application as a
 5     where a.status = 2
 6       and a.sex = 'male'
 7     # 不符合最左前缀原则,无法使用复合索引
8 注:针对此问题,如果字段对应值较少,可列出字段所有值,从而利用索引 9 10 # 现有索引 sex、cycle、status 11 select * 12 from application as a 13 where a.sex in('male', 'female') 14 and a.cycle = 2 15 and a.status = 4 
      2、符合最左前缀查询,若遇到第一个范围查询则其后的列无法再使用索引
 1     # 现有复合索引sex、cycle、status
 2  
 3     select *
 4     from application as a
 5     where a.sex = 'male'
 6       and a.cycle > 2
 7       and a.status = 3
 8     # 复合索引中的第二列使用了范围查询,第三列status无法再使用索引
 9     注:多个等值查询无此限制,即in无次限制
10       
# 现有复合索引sex、cycle、status
11 12 select * 13 from application as a 14 where a.sex = 'male' 15 and a.cycle in(3, 4) 16 and a.status = 3 17 # 使用in代替范围查询

         3、索引选择性需要尽量高,且前缀索引长度需要尽量合适

            注:尽量接近与完整列的”基数“

         4、覆盖索引

            定义:查询的列需要都在索引中,但不一定要使用索引
            作用:减少I/O的次数,提高查询速度

         5、利用索引进行排序

          规则:1、索引列顺序和order by子句序列完全一样,且所有列的排序方向相同。    
1         # 现有索引cycle、status
2             
3         select *
4         from application as a
5         order by a.cycle, a.status desc
6         # cycle 与 status 的排列顺序不同,无法使用索引排序
                    2、多表关联时,order by子句引用的字段全为第一个表时,才能使用索引排序。 
1        # 现有索引application.cycle, auto_cal_list.status
2           
3        select *
4        from application as a
5        inner jion auto_call_list as l on a.id = l.application_id
6        where a.status = 4
7        order by a.cycle, l.status
8        # order by子句有第二个
                    3、需要满足最左前缀规则,除非前代列为常量时。

    4、使用索引时的 I/O

         背景:现有表product,共有100万条数据,有一多列索引(actor、title、prod_id)        
         现有以下两条不同的sql进行查询:
1    select *  from product where actor = 'SE' and title like '%AP%'
2 
3    select *  from product
4    join(
5      select pro_id  from product  
6      where actor = 'SE' and title like '%AP%'
7    )as t1 on t1.prod_id = product.prod_id
   结果集情况:                                      结果:                                            分析:
  1、SE有:30000  其中AP:20000    1、每秒5次          2、每秒5次         1、3万+2万*列(数据I/o) 2、2万+join+2万*列
  2、SE有:30000  其中AP:40          1、每秒7次          2、每秒35次       2、3万+40*列                     2、40+join+40*列
  3、SE有:50        其中AP:10          1、每秒2400次    2、每秒2000次   3、50+10*列                       2、10+join+10*列
      注:当索引覆盖的行过大时(超过表数据的3%),选择器将选择使用全表扫描。

  三、sql优化之减少数据量

     1、减少select返回的数据量,尽量使用 select 列名 代替 select *。
1       select *
2       from application as a
3         
4       select a.id, a.user_id
5       from application as a
      2、使用 limit 限制返回的数据量(orm中有无limit的比较)。   
1      Application.filter().limit(1).execute()
2 
3      Application.filter().first()    
     使用limit的好处:
       1、使用 limit 查询到足够的数据就会停止查询,直接返回数据;无limit会将条件查询完才会返回相应的数
            据。
       2、两条语句虽然都是取一条数据,但使用limit只查一条数据,然后返回一条数据;无limit会查出所有数据,
             然后返回所有数据,但只取第一条数据。
       注:偏移量过大时使用limit同样会消耗资源。
    
 
posted @ 2018-10-15 22:28  雨落滴碎荷  阅读(157)  评论(0编辑  收藏  举报