我有以下查询:
SELECT t.id
FROM account_transaction t
JOIN transaction_code tc ON t.transaction_code_id = tc.id
JOIN account a ON t.account_number = a.account_number
GROUP BY tc.id
当我执行EXPLAIN
时,第一行显示了以下内容:
table: t
type: ALL
possible_keys: account_id,transaction_code_id,account_transaction_transaction_code_id,account_transaction_account_number
key: NULL
rows: 465663
为什么键为NULL?
答案 0 :(得分:48)
您可能遇到的另一个问题是数据类型不匹配。例如,如果您的列是字符串数据类型(CHAR,例如),并且您的查询未引用数字,则MySQL将不使用该索引。
SELECT * FROM tbl WHERE col = 12345; # No index
SELECT * FROM tbl WHERE col = '12345'; # Index
消息来源:今天刚刚解决了同样的问题,并在MySQL 5.1上学到了很多。 :)
编辑:验证此内容的其他信息:
mysql> desc das_table \G
*************************** 1. row ***************************
Field: das_column
Type: varchar(32)
Null: NO
Key: PRI
Default:
Extra:
*************************** 2. row ***************************
[SNIP!]
mysql> explain select * from das_table where das_column = 189017 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: das_column
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 874282
Extra: Using where
1 row in set (0.00 sec)
mysql> explain select * from das_table where das_column = '189017' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: das_column
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 34
ref: const
rows: 1
Extra:
1 row in set (0.00 sec)
答案 1 :(得分:16)
这可能是因为统计数据被破坏了,或者因为它知道两个表之间总是有1:1的比例。
您可以强制在查询中使用索引,看看是否会加快速度。如果是,请尝试运行ANALYZE TABLE以确保统计信息是最新的。
通过指定USE INDEX(index_list),您可以告诉MySQL只使用其中一个命名索引来查找表中的行。替代语法IGNORE INDEX(index_list)可用于告诉MySQL不使用某些特定索引或索引。如果EXPLAIN显示MySQL正在使用可能索引列表中的错误索引,则这些提示很有用。
您还可以使用FORCE INDEX,其作用类似于USE INDEX(index_list),但另外还假设表扫描非常昂贵。换句话说,只有在无法使用某个给定索引查找表中的行时才使用表扫描。
每个提示都需要索引的名称,而不是列的名称。 PRIMARY KEY的名称是PRIMARY。要查看表的索引名称,请使用SHOW INDEX。
答案 2 :(得分:7)
group by
(=隐式order by
)的索引
...
GROUP BY tc.id
group by对tc.id进行了隐式排序
tc.id未列为可能的密钥。
但是t.transaction_id 是。
将代码更改为
SELECT t.id
FROM account_transaction t
JOIN transaction_code tc ON t.transaction_code_id = tc.id
JOIN account a ON t.account_number = a.account_number
GROUP BY t.transaction_code_id
这会将潜在索引transaction_code_id
放入视图中。
联接的索引
如果连接(几乎)完全连接三个表,则不需要使用索引,因此MySQL不会。
不使用索引的其他原因
如果正在考虑的大部分行(40%IIRC)填充相同的值。 MySQL不使用索引。 (因为没有使用索引更快)