指示MySQL将WHERE子句应用于先前WHERE子句返回的行

时间:2013-10-06 20:18:16

标签: mysql query-optimization where

我有以下查询:

  SELECT dt_stamp
    FROM claim_notes
   WHERE type_id             = 0
     AND dt_stamp           >= :dt_stamp
     AND DATE( dt_stamp )    = :date
     AND user_id             = :user_id
     AND note             LIKE :click_to_call
   ORDER BY dt_stamp
   LIMIT 1

claim_notes表有大约五十万行,所以这个查询运行得非常慢,因为它必须搜索未编制索引的note列(我无法做任何事情)。我知道,当应用type_iddt_stampuser_id条件时,我会搜索大约60行而不是50行。但MySQL似乎没有按顺序应用这些。我想要做的是看看是否有办法告诉MySQL只将note LIKE :click_to_call条件应用于满足前一条件的行,这样它就不会搜索具有这种条件的所有行。

我想出的是:

  SELECT dt_stamp
    FROM (
            SELECT *
              FROM claim_notes
             WHERE type_id           = 0
               AND dt_stamp         >= :dt_stamp
               AND DATE( dt_stamp )  = :date
               AND user_id           = :user_id
         )
     AND note LIKE :click_to_call
   ORDER BY dt_stamp
   LIMIT 1

这非常有效。我只是想知道这是否是正确的方法,或者是否有更正式的方式来处理它。

2 个答案:

答案 0 :(得分:0)

不要使用派生表解决方案,因为它不具备性能。令我感到惊讶的是,拥有=>=运算符的MySQL首先用于LIKE

无论如何,我会说你可以尝试在这些字段上添加一些索引,看看会发生什么:

ALTER TABLE claim_notes ADD INDEX(type_id, user_id);
ALTER TABLE claim_notes ADD INDEX(dt_stamp);

后一个索引实际上不会改进对索引的搜索,而是对结果的排序。

当然,拥有EXPLAIN查询会有所帮助。

答案 1 :(得分:0)

没有必要这样做。如果WHERE子句中的多个术语由AND分隔,则MySQL优化器可以处理它。基本上,它知道如何“应用所有可以使用索引的条件,然后将未编制索引的表达式应用于剩余的行。”

但选择正确的指数很重要。对于一系列AND项而言,多列索引最适合单个索引。 MySQL可以应用索引交集,但这比使用单个索引查找相同的行要有效得多。

一些逻辑规则适用于创建多列索引:

  • 唯一列的条件优先于非唯一列的条件。

  • 平等条件(=)优先于范围(>=INBETWEEN!=等。)

  • 在用于范围条件的索引中的第一列之后,后续列将不使用索引。

  • 大多数情况下,在列上搜索函数的结果(例如DATE(dt_stamp))将不会使用索引。在这种情况下,最好存储DATE数据类型并使用=代替>=

  • 如果条件匹配>表格的20%,MySQL可能会决定跳过索引并进行表格扫描。

以下是我自己和Percona的同事们的一些网络研讨会,以帮助解释索引设计:

您可以免费获取这些网络研讨会的幻灯片,并免费查看录制内容,但录制内容需要注册。