MySQL 5.5
我正在尝试为查询找到正确的索引。
表:
create table trans (
trans_id int(11) not null auto_increment,
acct_id int(11) not null,
status_id int(11) not null,
trans_transaction_type varchar(5) not null,
trans_amount float(9,3) default null,
trans_datetime datetime not null default '0000-00-00 00:00:00',
primary key (trans_id)
)
查询:
select trans_id
from trans
where acct_id = _acctid
and transaction_type in ('_1','_2','_3','_4')
and trans_datetime between _start and _end
and status_id = 6
基数:
select *
from information_schema.statistics
where table_name='trans'
结果:
trans_id 424339375
acct_id 12123818
trans_transaction_type 70722272
trans_datetime 84866726
status_id 22
我正在尝试查找查询的正确索引是什么?
alter table trans add index (acct_id, trans_transaction_type, trans_datetime, status_id);
alter table trans add index (acct_id, trans_datetime, trans_transaction_type, status_id);
etc...
哪个列在索引中排在第一位?
目标是查询速度/性能。磁盘空间使用无关紧要。
答案 0 :(得分:0)
索引表的基础是使查询轻松以提高性能,要添加的第一个索引应始终是表的主键(在本例中为trans_id),之后,其他id列应该也被编入索引。
alter table trans add index (trans_id, acct_id, status_id);
除非您根据它们过于频繁地查询,否则不需要其他字段作为索引。
答案 1 :(得分:0)
计划A
从WHERE
的任何col = constant
子句开始。然后继续前进一个。
建议您添加以下两项,因为要预测哪个更好会更容易:
INDEX(acct_id, status_id, transaction_type)
INDEX(acct_id, status_id, trans_datetime)
计划B
trans_id
列表中你真的只有SELECT
吗?如果是这样,那么把它变成"覆盖"指数。这是一个索引,其中整个操作可以在索引所在的BTree中执行,从而避免不得不覆盖数据。
要构建此类,首先构建最佳非覆盖索引,然后在查询中添加 where 中提到的其余字段。这些都应该有效:
INDEX(acct_id, status_id, trans_datetime, transaction_type, trans_id)
INDEX(acct_id, status_id, transaction_type, trans_datetime, trans_id)
前两个字段可以按任意顺序排列(两者都是' =')。最后两个字段可以按任意顺序排列(两者都无法用于查找行;它们仅用于'覆盖')。
我建议不要在索引中使用超过5列。
More info in my Index Cookbook
备注强>
执行EXPLAIN SELECT
。你应该看到'使用索引'什么时候覆盖'索引。
我认为EXPLAIN's
Key_len
会(在所有情况下都显示)仅显示acct_id
和status_id
的组合长度。
您正在使用存储过程?如果SP中的版本运行速度明显慢于您的实验,则可能需要重新编码为CONCAT
,PREPARE
和EXECUTE
查询。