我有以下查询:
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_id
,dt_stamp
和user_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
这非常有效。我只是想知道这是否是正确的方法,或者是否有更正式的方式来处理它。
答案 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可以应用索引交集,但这比使用单个索引查找相同的行要有效得多。
一些逻辑规则适用于创建多列索引:
唯一列的条件优先于非唯一列的条件。
平等条件(=
)优先于范围(>=
,IN
,BETWEEN
,!=
等。)
在用于范围条件的索引中的第一列之后,后续列将不使用索引。
大多数情况下,在列上搜索函数的结果(例如DATE(dt_stamp)
)将不会使用索引。在这种情况下,最好存储DATE
数据类型并使用=
代替>=
。
如果条件匹配>表格的20%,MySQL可能会决定跳过索引并进行表格扫描。
以下是我自己和Percona的同事们的一些网络研讨会,以帮助解释索引设计:
您可以免费获取这些网络研讨会的幻灯片,并免费查看录制内容,但录制内容需要注册。