• MySQL Index Merge Optimization


          Index Merge用在通过一些range scans得到检索数据行和合并成一个整体。合并可以通过 unions,intersections,或者unions-intersection运用在底层的扫描上。合并Index scans结果只能在一个表中,不能合并多张表的scans结果;

         在explain执行计划输出中,index merge方法出现在 type 列,显示index merge,这种情况下key 列显示一列使用indexes,并且key_len列包含一列这些indexes 的最长部分;

         Examples:

    SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;
    
    SELECT * FROM tbl_name
      WHERE (key1 = 10 OR key2 = 20) AND non_key=30;
    
    SELECT * FROM t1, t2
      WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%')
      AND t2.key1=t1.some_col;
    
    SELECT * FROM t1, t2
      WHERE t1.key1=1
      AND (t2.key1=t1.some_col OR t2.key2=t1.some_col2);

      Index Merge 方法有许多access算法 ( Extra 列 Explain 输出):

    Using intersect(...)
    
    Using union(...)
    
    Using sort_union(...)
       
        1:如果查询语句在含有复杂的内嵌的深度and / or where语句,Mysql不会选择最佳的执行计划,
    (x AND y) OR z = (x OR z) AND (y OR z)
    (x OR y) AND z = (x AND z) OR (y AND z)

        2:index merge 不适用在full-text index;

       

    The Index Merge Intersection Access Algorithm

        该access算法在运用在,当where子句中不同的index range conditions用 and 组合时:

           1:index包括 N部分(所有index部分都包含):

    key_part1=const1 AND key_part2=const2 ... AND key_partN=constN

           2:  任何innodb主键上范围条件;

    SELECT * FROM innodb_table WHERE primary_key < 10 AND key_col1=20;
    
    SELECT * FROM tbl_name
      WHERE (key1_part1=1 AND key1_part2=2) AND key2=2;

           Index merge intersection 算法同时在所有使用的indexes上执行scan,并且从合并的Index扫描中产生行序列的交集;

           如果查询中的所有列都被使用的indexes所涵盖,完整的数据行不会被回访(只访问索引数据)(此时explain 输出包含显示using index 在extra列):

    SELECT COUNT(*) FROM t1 WHERE key1=1 AND key2=1;

         如果使用的indexes并不涵盖查询中的所有列,完整的数据行(基表的数据行)只会在范围条件被所有使用的Indexes都满足的情况下才会被回访;

         如果在innodb table中,一个合并条件是在主键上,则他不会被使用在基表数据行的回访,被用在过滤其他条件回访返回的数据行;

    index merge union access algorithm

          该算法试用在表的where语句在不同的index上的不同范围条件的 Or 组合:

    SELECT * FROM t1 WHERE key1=1 OR key2=2 OR key3=3;
    
    SELECT * FROM innodb_table WHERE (key1=1 AND key2=2) OR
      (key3='foo' AND key4='bar') AND key5=5;

    Index Merge sort-union access algorithm

    SELECT * FROM tbl_name WHERE key_col1 < 10 OR key_col2 < 20;
    
    SELECT * FROM tbl_name
      WHERE (key_col1 > 10 OR key_col2 = 20) AND nonkey_col=30;

     sort-union algorithm 和 the union algorithm 之间的区别在于必须首先获得所有的rows,并且对其排序被返回;

    mysql> explain select * from employees where  emp_no < 257654 and hire_date = '1990-09-06';
    +----+-------------+-----------+-------------+-------------------+-------------------+---------+------+------+-------------------------------------------------+
    | id | select_type | table     | type        | possible_keys     | key               | key_len | ref  | rows | Extra                                           |
    +----+-------------+-----------+-------------+-------------------+-------------------+---------+------+------+-------------------------------------------------+
    |  1 | SIMPLE      | employees | index_merge | PRIMARY,inx_hi_dt | inx_hi_dt,PRIMARY | 7,4     | NULL |   16 | Using intersect(inx_hi_dt,PRIMARY); Using where |
    +----+-------------+-----------+-------------+-------------------+-------------------+---------+------+------+-------------------------------------------------+
    1 row in set (0.09 sec)
    mysql> explain select * from employees where  emp_no < 257654 or  hire_date = '1990-09-06';
    +----+-------------+-----------+-------------+-------------------+-------------------+---------+------+--------+---------------------------------------------+
    | id | select_type | table     | type        | possible_keys     | key               | key_len | ref  | rows   | Extra                                       |
    +----+-------------+-----------+-------------+-------------------+-------------------+---------+------+--------+---------------------------------------------+
    |  1 | SIMPLE      | employees | index_merge | PRIMARY,inx_hi_dt | PRIMARY,inx_hi_dt | 4,3     | NULL | 149716 | Using union(PRIMARY,inx_hi_dt); Using where |
    +----+-------------+-----------+-------------+-------------------+-------------------+---------+------+--------+---------------------------------------------+
    1 row in set (0.00 sec)
    mysql> desc select  birth_date  from  employees where birth_date ='1961-07-09' and hire_date ='1986-06-29';
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------------------+
    | id | select_type | table     | type        | possible_keys       | key                 | key_len | ref  | rows | Extra                                                          |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------------------+
    |  1 | SIMPLE      | employees | index_merge | inx_hi_dt,idx_br_dt | idx_br_dt,inx_hi_dt | 3,3     | NULL |    1 | Using intersect(idx_br_dt,inx_hi_dt); Using where; Using index |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------------------+
    1 row in set (0.00 sec)
    mysql> desc select  birth_date  from  employees where birth_date ='1961-07-09' or  hire_date ='1986-06-29';
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+-----------------------------------------------+
    | id | select_type | table     | type        | possible_keys       | key                 | key_len | ref  | rows | Extra                                         |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+-----------------------------------------------+
    |  1 | SIMPLE      | employees | index_merge | inx_hi_dt,idx_br_dt | idx_br_dt,inx_hi_dt | 3,3     | NULL |  166 | Using union(idx_br_dt,inx_hi_dt); Using where |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+-----------------------------------------------+
    1 row in set (0.02 sec)
    mysql> desc select  birth_date  from  employees where birth_date < '1950-07-09' or  hire_date < '1970-06-29';
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    | id | select_type | table     | type        | possible_keys       | key                 | key_len | ref  | rows | Extra                                              |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    |  1 | SIMPLE      | employees | index_merge | inx_hi_dt,idx_br_dt | idx_br_dt,inx_hi_dt | 3,3     | NULL |    2 | Using sort_union(idx_br_dt,inx_hi_dt); Using where |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    1 row in set (0.00 sec)
    mysql> desc select  birth_date  from  employees where birth_date < '1950-07-09' or  hire_date = '1986-06-29';
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    | id | select_type | table     | type        | possible_keys       | key                 | key_len | ref  | rows | Extra                                              |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    |  1 | SIMPLE      | employees | index_merge | inx_hi_dt,idx_br_dt | idx_br_dt,inx_hi_dt | 3,3     | NULL |  111 | Using sort_union(idx_br_dt,inx_hi_dt); Using where |
    +----+-------------+-----------+-------------+---------------------+---------------------+---------+------+------+----------------------------------------------------+
    1 row in set (0.00 sec)
  • 相关阅读:
    第二节:简单工厂模式(静态工厂模式)
    第一节:不使用设计模式的传统方式
    第三章:设计模式概述
    第二节:类与类之间的关系
    高斯混合模型(GMM)
    随机森林
    LDA主题模型
    Adaboost算法
    线性代数
    k-means聚类
  • 原文地址:https://www.cnblogs.com/onlysun/p/4519633.html
Copyright © 2020-2023  润新知