美文网首页
SQL语句和索引优化

SQL语句和索引优化

作者: LittleTrue | 来源:发表于2018-10-17 21:50 被阅读0次

    sql语句优化

    1、尽量不要使用select * ,需要哪些字段就拿哪些
    2、Oracle和myslq中采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
    3、用EXISTS替代IN、用NOT EXISTS替代NOT IN。参考
    (小表驱动大表: in后面跟的是小表,exists后面跟的是大表。简记:in小,exists大。)
    4、索引使用,参考下面
    5、开启慢查询日志检测慢查询
    6、show processlist查看一直在频繁执行的语句, 对其进行优化
    7、使用explain分析SQL.在 explain的帮助下,您就知道什么时候该给表添加索引,以使用索引来查找记录从而让select 运行更快。
    8、通常对列进行计算都会使得索引失效, 所以不要在数据层处理, 最好在业务逻辑中编写计算, FROM_UNIX时间转化除外
    9、join连接时, 注意大表和小表的问题, 驱动表应该是小表。
    当进行多表连接查询时, [驱动表] 的定义为:
    1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表]
    2)未指定联接条件时,行数少的表为[驱动表](Important!)
    忠告:如果你搞不清楚该让谁做驱动表、谁 join 谁,请让 MySQL 运行时自行判断
    既然“未指定联接条件时,行数少的表为[驱动表]”了,而且你也对自己写出的复杂的 Nested Loop Join 不太有把握(如下面的实例所示),就别指定谁 left/right join 谁了,请交给 MySQL优化器 运行时决定吧。


    索引相关优化

    最基础:索引的使用,尽量能够做到一一对应每条数据表中的数据。
    1、表的主键、外键必须有索引; (主键数据库会自动创建, 外键如果没声明不会)
    2、数据量超过300的表应该有索引;
    3、经常与其他表进行连接的表,在连接字段上应该建立索引;
    4、经常出现在Where子句中的字段,特别是大表的字段,应该建立索引;
    5、索引应该建在选择性高的字段上;
    6、索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引;
    7、复合索引的建立需要进行仔细分析;尽量考虑用单字段索引代替:

    A、正确选择复合索引中的主列字段,一般是选择性较好的字段; 
    B、复合索引的几个字段是否经常同时以AND方式出现在Where子句中?
    单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引;
    C、如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引; 
    D、如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段; 
    E、如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引;
    

    8、频繁进行数据操作的字段,不要建立索引, 这个的取舍一般靠意会,如果查询10次以上才更新一次我觉得还是可以建立的;

    9、索引不会包含有NULL值的列,所以在数据库设计上不要让默认为null。 或者NULL必须时为了查询完整性不要包括NULL的字段,

    一般建议设置所有字段为not null,并设置默认值为' '(判断空字符用=''或者 <>''来进行处理,此处辟谣<>并不会使索引失效), NULL/null 是指没有值,而 ' ' 则表示值是存在的,只不过是个空值。

    'IS NULL IS NOT NULL' 只针对可以为空的字段的判断, 并且(在可以为空字段上判断)会导致索引失效, 所以在一些关键字段上, 是万万不能加NULL判断的
    而对于已经有 NOT NULL 修饰的字段来说,不要再使用 IS NULL 或者 IS NOT NULL 来作为查询条件,没有意义。

    聚合函数,count(), min(), sum(), 将会忽略 NULL 值

    要设置默认类型为'' , 不属于输入空格符, id相关可设置为0 (mysql自增id从1开始,所以不会产生影响)

    10、什么样的字段不适合建索引?
    一般来说,列的值唯一性太小(如性别,类型什么的),不适合建索引(怎样叫太小?一半说来,同值的数据超过表的百分之15,那就没必要建索引了)
    太长的列,可以选择只建立部分索引,(如:只取前十位做索引)

    非聚簇索引存储了对主键的引用,如果select字段不在非聚簇索引内,
    就需要跳到主键索引(上图中从右边的索引树跳到左边的索引树),再获取select字段值
    
    如果非聚簇索引值重复率高,那么查询时就会大量出现上图中从右边跳到左边的情况,导致整个流程很慢
    

    11、多列查询该如何建索引?
    一次查询只能用到一个索引

    每个索引在数据库中都是一个索引树,其数据节点存储了指向实际
    数据的指针,如果用一个索引来查询,其原理就是从索引树上去检索,
    并获得这些指针,然后去取出数据,试想,如果你通过一个索引,得到过滤后的指针,这时,你的另一个条件索引如果再过滤一遍,
    将得到2组指针的集合,如果这时候取交集,未必就很快,
    因为如果每个集合都很大的话,取交集的时候,等于扫描2个集合,效率会很低,所以没法用2个索引。
    

    所以 首先枪毙 a,b各建索引方案
    a还是b? 谁的区分度更高(同值的最少),建谁!
    当然,联合索引也是个不错的方案,ab,还是ba,则同上,区分度高者,在前

    12、orderby 中的字段--一般是时间,
    当order by 字段出现在where条件中时,才会利用索引而无需排序操作。其他情况,order by不会出现排序操作。
    如果最终的结果集是以order by字段为条件筛选的,将order by字段加入索引,并放在索引中正确的位置,会有明显的性能提升。
    ,因为如果建立了索引, 查询是只需要对索引的前几个进行提取就行, 省略了sort操作
    一般如果只是需求最新数据放前面, 完全可以针对唯一自增id做排序, 这样就启用了主键索引来进行排序, 效率提升, 也不用对时间列再做索引

    13、[重要]当大表关联小表时(数据量差异95%以上), 没必要在大表创建小表的索引。


    其实or的效率为O(n),而in的效率为O(log2n)
    https://blog.csdn.net/weixin_40609759/article/details/79998911

    参考
    参考


    相关文章

      网友评论

          本文标题:SQL语句和索引优化

          本文链接:https://www.haomeiwen.com/subject/yxzrzftx.html