代码之家  ›  专栏  ›  技术社区  ›  Tom

mysql复合索引列顺序与性能

  •  1
  • Tom  · 技术社区  · 6 年前

    我有一个表,大约有500000行,我正在测试它的两个复合索引。第一个索引将按列排序放在最后,第二个索引的顺序相反。

    我不明白的是,为什么第二个索引通过估计要扫描的30行而不是第一个查询的889行来提供更好的性能,因为我觉得第二个索引不能正确使用,因为排序依据列不是最后一个。有人能解释为什么会这样吗?如果两个索引都存在,MySQL更喜欢第一个索引。

    请注意,第二个解释将可能的\键列为空,但仍然列出了所选的键。

    1)第一指标

    ALTER TABLE user ADD INDEX test1_idx (city_id, quality);
    

    (基数12942)

    EXPLAIN SELECT * FROM user u WHERE u.city_id = 3205 ORDER BY u.quality DESC LIMIT 30;
    +----+-------------+-------+--------+---------------+-----------+---------+----------------+------+-------------+
    | id | select_type | table | type   | possible_keys | key       | key_len | ref            | rows | Extra       |
    +----+-------------+-------+--------+---------------+-----------+---------+----------------+------+-------------+
    |  1 | SIMPLE      | u     | ref    | test1_idx     | test1_idx | 3       | const          |  889 | Using where | 
    +----+-------------+-------+--------+---------------+-----------+---------+----------------+------+-------------+
    

    2)第二个索引(相同字段的顺序相反)

    ALTER TABLE user ADD INDEX test2_idx (quality, city_id);
    

    (基数7549)

    EXPLAIN SELECT * FROM user u WHERE u.city_id = 3205 ORDER BY u.quality DESC LIMIT 30;
    +----+-------------+-------+--------+---------------+-----------+---------+----------------+------+-------------+
    | id | select_type | table | type   | possible_keys | key       | key_len | ref            | rows | Extra       |
    +----+-------------+-------+--------+---------------+-----------+---------+----------------+------+-------------+
    |  1 | SIMPLE      | u     | index  | NULL          | test2_idx | 5       | NULL           |  30  | Using where | 
    +----+-------------+-------+--------+---------------+-----------+---------+----------------+------+-------------+
    

    更新:

    第二个查询在现实场景中执行得不好,而第一个查询如预期的那样。我仍然好奇为什么mysql explain提供了如此相反的信息。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Jacob    6 年前

        2
  •  1
  •   wa56    6 年前

    SELECT * FROM user u WHERE u.city_id = 3205 ORDER BY u.quality DESC LIMIT 30;
    

    FORCE INDEX(test1_idx)