我有一个包含30,000行(并且正在增长)的表,我与另一个表连接。一些页面,我需要运行大约100多个这样的查询,事情变得缓慢。如果我EXPLAIN
查询,我注意到一个表使用主键并且速度很快,但另一个表使用其中一个索引,这不是最好的。这是一个概述:
SIMPLE | acc_entries | ref | ledger,date,type,status,status_ledger_date_type | type | 1 | const | 15359 | Using where
这是一个示例查询:
SELECT SUM(usd) AS total FROM acc_entries
LEFT JOIN acc_ledgers ON acc_entries.ledger = acc_ledgers.id
WHERE acc_entries.status = 1 AND
acc_ledgers.account = 3004 AND
date >= '2011-01-01' AND
date <= '2011-08-30' AND
type = 'credit'
正如您所看到的,我在我的WHERE中使用字段status
,ledger
(与acc_ledgers.account
加入的字段),date
和{{ 1}}。所有这些字段都有索引。但是,还有一个特定的索引,以相同的顺序用于所有这些索引。它被称为type
,正如您所看到的,它是MySQL考虑使用的索引之一。但是,最后MySQL选择使用status_ledger_data_type
作为索引。这有大约15,000个可能的行(表的一半),而另一个组合索引只有一小部分。所以我的问题是:为什么当一个更好的索引可用时,MySQL会选择这个索引,我该如何防止这个?
答案 0 :(得分:1)
您可以尝试使用索引提示来强制使用所需的索引。
答案 1 :(得分:0)
实际上,您希望索引基于较小的粒度。您的Acc_Entries表中的分类帐将连接到ITS的主要ID索引上的ACC_Ledgers表,因此Acc_Ledgers实际上并未使用WHed子句的Ledger部分。您的索引应与常见查询的WHERE子句尽可能匹配。在这种情况下,我会在
上有一个索引(帐户,状态,类型,日期)
帐户为第一个,结果集较小的原因。你可以有5,000个条目。其中,一个帐户的300个条目,因此您已经消除了大量数据。然后,300的状态...,您可以有100 @状态1,100 @状态2,100 @状态3,所以您现在已经通过其他类型和日期标准减少了设置等。< / p>
你的查询完全没问题...只是个人写作风格,我尝试用WHERE条件编写我的查询,因为它也在同一序列中与索引紧密匹配,所以我首先要有Account子句,然后状态,类型和日期......但同样,这也是写作查询的个人风格。