【问题标题】:Why is MySQL not using indexes with composite WHERE IN?为什么 MySQL 不使用复合 WHERE IN 的索引?
【发布时间】:2012-03-23 19:11:30
【问题描述】:

我正在尝试通过复合索引从具有 PRIMARY KEY (a, b) 的表中获取几条记录

SELECT * FROM table WHERE (a, b) IN ((1,2), (2,4), (1,3))

问题是,即使我 FORCE INDEX (PRIMARY),MySQL 也没有使用索引。
EXPLAIN SELECT 显示 null possible_keys。

为什么没有 possible_keys?

通过复合键检索多行的最佳方法是什么:

  • 使用 OR
  • 使用 UNION ALL
  • 使用 WHERE () IN ((),())

附:查询结果等于

SELECT * FROM table WHERE (a = 1 AND b = 2) OR (a = 2 AND b = 4) OR (a = 1 AND b = 3)

谢谢

【问题讨论】:

    标签: mysql indexing composite-key query-performance where-in


    【解决方案1】:

    如果查询通过组合WHERE ... IN仅从索引中选择字段(或者如果表没有其他字段),则将使用索引:

    SELECT a,b FROM `table` WHERE (a, b) IN ((1,2), (2,4), (1,3))
    

    否则将不会被使用。 解决方法是使用派生查询:

    SELECT t.* FROM (SELECT a, b FROM `table` WHERE (a, b) IN ((1,2), (2,4), (1,3))) AS o INNER JOIN `table` AS t ON (t.a = o.a AND t.b = o.b)
    

    解释选择:

    id  select_type table   type    possible_keys   key key_len ref rows    Extra
    1   PRIMARY <derived2>  ALL NULL    NULL    NULL    NULL    2   
    1   PRIMARY t   eq_ref  PRIMARY PRIMARY 2   o.a,o.b 1   
    2   DERIVED table   index   NULL    PRIMARY 2   NULL    6   Using where; Using index
    

    【讨论】:

      【解决方案2】:

      强烈希望为某个列建立索引,您是否考虑过创建一个新列:a_b,基本上是CONCAT(a, '-', b),然后比较一下(WHERE a_b = {$id1}-{$id2})?

      每个表只能有一个 PRIMARY 列。您不能同时“索引主要”ab

      【讨论】:

      • 使用CONCAT(a, '-', b) 对我来说不是一个好选择,因为如果我在字段值中有'-',它可能会失败。我的 PRIMARY KEY 是多列的,所以它同时包含 ab
      • CONCAT(a, '!-!', b) - 你曾经使用过这个值吗? :)
      • 我的表包含数亿条记录,我认为索引字符串列不会提高性能。我宁愿使用 UNION ALL 进行批量复合选择。
      【解决方案3】:

      尝试在 a、b 列上创建组合索引。

      索引不需要是主键,它仍然可以提供很多帮助。

      在此处了解有关您的问题的更多信息:http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-09
        • 2012-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-30
        • 1970-01-01
        相关资源
        最近更新 更多