【问题标题】:Slow MySQL (InnoDB) query despite join on indexed key, why?尽管在索引键上加入了缓慢的 MySQL(InnoDB)查询,为什么?
【发布时间】:2011-10-28 18:33:35
【问题描述】:

你知道为什么这个请求会很慢(在其他速度很快的 MySQL 服务器上需要 1.7 秒):

SELECT DISTINCT TABLE_A.keyA 
FROM TABLE_A,TABLE_B 
WHERE TABLE_A.keyB= TABLE_B.keyB 
AND TABLE_A.fieldC in (0,2,5,7,8) LIMIT 20;

有了EXPLAIN给出的这个执行计划:

id    select_type table       type    possible_keys         key                   key_len   ref     rows     Extra 
1     SIMPLE      TABLE_B     index   PRIMARY               PRIMARY               8     NULL      10     Using index; Using temporary
1     SIMPLE      TABLE_A     ref     IDX_TABLE_A_KEY_B     IDX_TABLE_A_KEY_B     8     TABLE_B.keyB     25455     Using where

其他元素:

  • 表 TABLE_A 有 300 000 行
  • TABLE_A.keyA 是 TABLE_A 的主键
  • TABLE_A.keyB 是 TABLE_B 的主键 keyB 的外键; 表 TABLE_B 有 10 行;
  • 99% 的 TABLE_A 有 fieldC=1 并且 1% 的表有 fieldC 在 (0,2,5,7,8) (这就是为什么这个字段没有被索引;编辑这个子句没有问题,因为 SELECT使用相同的子句但不与 TABLE_B 连接很快);
  • 在我看来,是 JOIN 有罪,因为在表上进行简单的 SELECT 很快;
  • 与另一个表 TABLE_C 的连接也很慢;
  • MySQL 版本:5.1.23a-maria-alpha

你有什么想法吗?

【问题讨论】:

    标签: mysql sql mariadb


    【解决方案1】:

    99% 的 TABLE_A 有 fieldC=1 并且 1% 的表有 fieldC 在 (0,2,5,7,8) (这就是为什么这个字段没有索引

    这将是为该列编制索引的绝佳理由。 您的查询只需要不到 1% 的表,因此索引将非常有选择性。

    【讨论】:

    • 你是对的。但是,表格的每一行在获得最后一个值之前都会更新此字段 10 次(它是一个状态)。这不会导致索引更新耗时吗?
    • 当然更新索引需要(一点)时间(以及一些磁盘空间来存储它)。但是索引使查询更快。这是一个权衡。
    • 就是这样。 SELECT 时间减少到 0,0012 秒!
    【解决方案2】:

    可能是IN 子句,它们往往很慢,你有TABLE_A.fieldC 的索引吗?

    【讨论】:

    • 正如我稍后添加的,相同的请求没有加入但相同的 IN 子句很快。
    • 没有加入它是一个不同的查询!您无法比较它们的速度。如果您确实需要改进,请尝试在 fieldC 上添加索引。
    • 太棒了,确实如此,请参阅 Thilo 的回答!
    【解决方案3】:
    SELECT DISTINCT TABLE_A.keyA 
    FROM TABLE_A 
    INNER JOIN TABLE_B ON TABLE_A.keyB = TABLE_B.keyB 
    WHERE 
    TABLE_A.fieldC IN (0, 2, 5, 7, 8) LIMIT 20;
    

    试试那个。

    【讨论】:

      【解决方案4】:

      试试

      SELECT DISTINCT TABLE_A.keyA 
      FROM TABLE_A
      WHERE TABLE_A.keyB IN (SELECT TABLE_B.keyB FROM TABLE_B )
      AND TABLE_A.fieldC in (0,2,5,7,8) LIMIT 20;
      

      【讨论】:

        【解决方案5】:

        在字段C 列上添加索引。 然后运行查询

        Select DISTINCT keyA from 
         (select keyA, keyB from TABLE_A where fieldC in (0,2,5,7,8)) 
        as temp STRAIGHT_JOIN TABLE_B on temp.keyB=TABLE_B.keyB limit 20
        

        尝试使用直接连接和内部连接。

        【讨论】:

        • 索引权限(参见 Thilo),但我无法更改请求的编写方式。
        猜你喜欢
        • 2018-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-13
        • 1970-01-01
        • 2012-04-01
        • 1970-01-01
        相关资源
        最近更新 更多