【问题标题】:mySQL Is non-clustering index + not indexed field still faster than 2 x not indexed fields?mySQL 非聚集索引 + 非索引字段仍然比 2 x 非索引字段快吗?
【发布时间】:2014-10-24 17:50:04
【问题描述】:

例如,我有 3 列的表: “id”、“a”、“b”

id 是主键 a - 没有索引的字段 b - 没有索引的字段

CREATE TABLE samples (id INT, a INT, b INT, PRIMARY KEY(id));

现在我想做一个选择查询:

SELECT * FROM samples where a = '77345' and b = '234234';

据我了解,如果我将有“a”和“b”字段的索引,这个查询将非常快,如下所示:

CREATE INDEX ab_index ON samples (a, b) USING BTREE;

问题:

如果我只为“a”字段添加索引(没有其他索引),上面的选择查询会更快:

CREATE INDEX a_index ON samples (a) USING BTREE;

如果是,会快多少?

【问题讨论】:

    标签: mysql sql indexing


    【解决方案1】:

    表格示例:

    create table samples (id int NOT NULL AUTO_INCREMENT, a int, b int, PRIMARY KEY(id));
    

    插入 2,483,308 条记录

    测试查询

    select * from samples where a = 3434 and b = 4389;
    

    没有索引:

    **Timing (as measured by the server):**
    
    Execution time: 0:00:0.57075288
    
    Table lock wait time: 0:00:0.00008100
    

    在 (a) 上有索引:

    CREATE INDEX a_index ON samples (a) USING BTREE;
    
    **Timing (as measured by the server):**
    
    Execution time: 0:00:0.00021302
    
    Table lock wait time: 0:00:0.00008300
    

    仅使用索引 (a, b):

    CREATE INDEX ab_index ON samples (a, b) USING BTREE;
    
    **Timing (as measured by the server):**
    
    Execution time: 0:00:0.00019394
    
    Table lock wait time: 0:00:0.00007600
    

    带有 (a) 和 (a, b) 索引:

    **Timing (as measured by the server):**
    
    Execution time: 0:00:0.00022304
    
    Table lock wait time: 0:00:0.00008300
    

    删除索引,不再有任何索引:

    **Timing (as measured by the server):**
    
    Execution time: 0:00:0.57105565
    
    Table lock wait time: 0:00:0.00008300
    

    再次使用 (a) 仅索引:

    Execution time: 0:00:0.00021866
    
    Table lock wait time: 0:00:0.00008700
    

    是的,只添加 (a) 索引会显着提高速度。

    奇怪的是,解释表明在存在 (a) 和 (a, b) 索引的情况下,mySQL 出于某种原因仍然使用 (a) 索引。

    explain select * from samples where a = 45 and b = 3456;
    

    +----+-------------+---------+------+---------- --------+---------+---------+--------+------+------ --------+

    |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 |

    +----+-------------+---------+------+---------- --------+---------+---------+--------+------+------ --------+

    | 1 |简单 |样品 |参考 | a_index,ab_index | a_index | 5 |常量 | 1 |使用位置 |

    +----+-------------+---------+------+---------- --------+---------+---------+--------+------+------ --------+

    【讨论】:

      【解决方案2】:

      如果不了解您的数据内容,“多快”问题确实很难回答。如果您只索引您的 a 列,并且您有一个大表,但 a 的不同值并不多,那么 MySQL 仍然需要扫描您的表的一大块。

      a 或仅b 上的索引可能(但不一定)比扫描整个表更快。如果不尝试真实数据,真的很难知道。这当然值得一试。

      专业提示:切勿在可能的情况下使用SELECT *,而是枚举所需列的名称。这是因为查询执行计划器有时会在知道不需要所有列时采取捷径。

      你给出的查询,改写成说

      SELECT id,a,b 
        FROM samples
       where a = '77345'
         and b = '234234'
      

      如果您在 (a,b,id) 上有一个索引,确实可以非常快。那是因为 MySQL 可以从索引中满足整个查询。它在索引中找到 a,然后找到 b。然后坐在那里是 id 值。这称为复合覆盖指数。值得一读。

      【讨论】:

      • 在我们的select查询中索引(a,b,id)不是必需的,(a,b)就足够了。但是(a)索引会比没有索引更快吗?
      • 我想你可能误解了我关于 (a,b,id) 的观点。该索引能够直接返回 id 的值来满足查询,而无需返回原始表。所以它更快,因为它需要更少的磁盘 io。
      • 但是(a)索引会比没有索引快吗?
      猜你喜欢
      • 2011-06-02
      • 2013-08-07
      • 1970-01-01
      • 2015-01-27
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 2021-01-14
      相关资源
      最近更新 更多