• #">补充:索引的选择逻辑#

    补充:索引的选择逻辑#

    Case1: 比如现有索引:KEY(x1,x3)、KEY(x2,x4)
    SQL如下:
    Copyselect from t where x1=xxx and x2>yyy;
    那么问题来了,x1、x2都有对应的索引,那MYSQL该如何选择索引呢?
    一般来说MYSQL会优先选择一个扫描行数少的KEY,作为最终的索引,比如x1是等值条件,x2是range条件,所以最终大概率是通过x1索引查询一次取id,再去回表找到x2列,使用x2>yyy的条件进行过滤。
    Case2:在执行SQL语句时有可能会同时查询多个索引。
    比如:现有索引:KEY(x1)、KEY(x2)
    SQL如下:
    Copyselect
    from table where x1=xxx and x2=yyy;
    那它的执行计划可能就是:先从x1索引数中取出x1=xxx的数据行,再从x2的索引树中取出x2=yyy的数据行,这两部分数据根据主键进行一次交集,再使用intersection交集后的结果去聚簇索引中回表。
    之前的例子中说的是,在x1和x2这两个索引中优先选一个扫描行数少的索引,先使用它查询,在拿着查询到的结果去回表。
    那,之所以示例9中的情况会出现,是因为可能存在如下的情况:
    (扫描x1的行数+扫描x2的行数)+ merge之后的行数 < 扫描x1或者x2的最少行数+回表的行数
    此外:如果想让一个SQL使用多个索引,也有硬性的条件:

    1. 如果使用联合索引,那联合索引中的每一个字段都需要出现在sql中,且必须是等值匹配。
    2. 通过主键查询+其他二级索引的等值匹配,也可能做一次多索引查询做交集后再回表。

    补充:如果你的SQL如下:
    Copyselect from table where x1=xxx or x2=yyy;
    依然有可能使用多个索引,然后对多个索引的结果取union并集
    Case3:如下SQL
    Copyselect
    from t1,t2 where t1.x1 = xxx and t1.x2 = t2.x2 and t2.x3 = yyy;
    sql中的有t1、t2两个表,前面的t1为驱动表,后面的t2为被驱动表。
    sql中的t1.x2 = t2.x2为关联条件。
    SQL在执行时会先使用t1.x1=xxx为条件先捞出一部分数据,此次操作会根据x1的索引情况而不同,可能是const、ref、index或者全表扫描all。
    假设第一次根据x1=xxx条件找到了2行数据(称这两行数据为A)。接下来会分别拿着这两行数据中的x2为新的条件,去t2表中查询,假设第一行数据的x2列值为123。他就会使用t2.x2=123 and t2.x3=yyy为新的条件在t2表找到匹配到的数据,和第一行数据关联起来。
    补充:
    这种联表查询的方式也叫做内连接,比如t2中有3行符合x2=123 ,那么它们都会被和A中的第一行拼接起来,作为最终的返回值。
    如果t2表中没有找到t2.x2=123的列,那么A中的第一行数据也不会被保留作为最终的返回值。
    那如果不想因为t2.x2中没有符合条件的列也将A中的第一行保留下来,那么可以使用外连接实现。如 left join on + 条件
    接着处理A中的第二行数据。