MySQL的索引相关知识学习


搜索关键字:
  • mysql b tree
  • mysql 索引 原理
  • mysql Composite index
  • mysql 联合索引
参考链接:
在MySQL中建立索引的原则

(1)最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如 a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整。

(2)=和in可以乱序,比如 a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。(不知道这句话的依据是什么?不过可以通过实际测试来检验一下)

(3)尽量选择区分度高的列作为索引,区分度的公式是count(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录。

(4)尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可(索引越少越好;原因:主要在修改数据时,每个索引都要进行更新,降低写速度)。

参考说明:

MySQL一次查询只能使用一个索引。如果要对多个字段使用索引,建立复合索引。创建多列索引的意义就是为了‘减少io操作’。

==

InnoDB使用B+Tree作为索引结构(聚集索引)。在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

在知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

因此,只要可以,请尽量在InnoDB上采用自增字段做主键。

 

==

MySQL can use multiple-column indexes for queries that test all the columns in the index, or queries that test just the first column, the first two columns, the first three columns, and so on. If you specify the columns in the right order in the index definition, a single composite index can speed up several kinds of queries on the same table.

==

Always check whether all your queries really use the indexes that you have created in the tables. Use the EXPLAIN statement, as described in Section 8.8.1, “Optimizing Queries with EXPLAIN”.

==

If a multiple-column index exists on col1 and col2, the appropriate rows can be fetched directly. If separate single-column indexes exist on col1 and col2, the optimizer attempts to use the Index Merge optimization (see Section 8.2.1.4, “Index Merge Optimization”), or attempts to find the most restrictive index by deciding which index excludes more rows and using that index to fetch the rows.

If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows. For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3).

MySQL cannot use the index to perform lookups if the columns do not form a leftmost prefix of the index. Suppose that you have the SELECT statements shown here:

SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
/* ... */
SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

If an index exists on (col1, col2, col3), only the first two queries use the index. The third and fourth queries do involve indexed columns, but (col2) and(col2, col3) are not leftmost prefixes of (col1, col2, col3).

参考说明2:

https://mariadb.com/kb/en/index-condition-pushdown/

  • 创建多列索引(列1,列2,列3)后的结构类似这样(index结构,附属列,附属列)
  • 附属列可能直接跟在叶节点上,或单独存放(这个没有看到说明)…
  • 附带可以说明单列索引就是多列索引一种形式,只不过没有附属列罢了…
更多参考链接:

=EOF=

,

《 “MySQL的索引相关知识学习” 》 有 7 条评论

  1. 或许你不知道的10条SQL技巧
    https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651960280&idx=1&sn=da519cff7081ab347eb1aaa4f0f4f408
    `
    (1)负向条件查询不能使用索引(not in/not exists都不是好习惯)
    (2)前导模糊查询不能使用索引(where desc like ‘%XX’ 不行,而 ‘XX%’ 可以)
    (3)数据区分度不大的字段不宜使用索引(经验上,能过滤80%数据时就可以使用索引)
    (4)在属性上进行计算不能命中索引
    (5)如果业务大部分是单条查询,使用Hash索引性能更好,例如用户中心
    (6)允许为null的列,查询有潜在大坑(如果name允许为null,索引不存储null值,结果集中不会包含这些记录。请使用not null约束以及默认值)
    (7)复合索引最左前缀,并不是值SQL语句的where顺序要和复合索引一致
    (8)使用ENUM而不是字符串
    (9)如果明确知道只有一条结果返回,limit 1能够提高效率
    (10)把计算放到业务层而不是数据库层,除了节省数据的CPU,还有意想不到的查询缓存优化效果
    (11)强制类型转换会全表扫描
    `

  2. 聊聊Mysql优化之索引优化
    https://mp.weixin.qq.com/s/6M0C2zEXik2NE7A7BIONFw
    `
    B-Tree索引的限制

    1)如果不是按照索引的最左列开始查找,则无法使用索引。
    如对上述user表查询 where age=20则无法使用到索引,因为age不是索引列中的最左数据列。

    2)不能跳过索引中的列。
    如对上述user表查询 where name=’aaa’ and interest=’足球’,则只能使用到索引的第一列,因为where条件中没有包含age这一列。
    `

  3. 哪些因素会导致慢查询?
    https://mp.weixin.qq.com/s/Edn_gPwcAHo5sYIzLJghzA
    `
    一 前言
    不管是开发同学还是DBA,想必大家都遇到慢查询(select,update,insert,delete 语句慢),影响业务稳定性。这里说的慢,有两个含义一是比正常的慢,有可能正常执行时间是10ms,异常的是100ms 。二是sql执行时间超过设置的慢查询标准比如500ms。

    本文从IT架构以及数据库纬度来分析导致sql执行慢的原因/场景,抛砖引玉,有不足之处还请大家多多提建议。

    二 基础知识
    几个会影响sql执行速度的因素:
    1、网络,各个节点之间的网络
    2、OS系统 ,即数据库服务器
    3、MySQL数据库本身

    三 基础系统层面
    3.1 网络层面
    3.2 受到影响IO的场景
    3.3 cpu 类型

    四 数据库层面
    4.1 没有索引,或者索引不正确
    4.2 隐式转换
    4.3 执行计划错误
    4.4 数据巨大
    4.5 MetaData Lock锁等待
    4.6 并发更新同一行
    4.7 数据分布不均
    4.8 sql 姿势不合理
    4.9 表结构设计
    4.10 innodb 刷脏页
    4.11 undo 没有被purge/回收
    `

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注