MySQL如何创建正确的索引
Posted
技术标签:
【中文标题】MySQL如何创建正确的索引【英文标题】:MySQL how to create a correct index 【发布时间】:2015-08-31 18:08:21 【问题描述】: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...
哪些列在索引中排在第一位?
目标是查询速度/性能。磁盘空间使用无关紧要。
【问题讨论】:
【参考方案1】:索引一个表的基础是让查询更轻以提高性能,要添加的第一个索引应该始终是表的主键(在这种情况下为trans_id),然后其他id列应该也被索引。
alter table trans add index (trans_id, acct_id, status_id);
其他字段不需要作为索引,除非您根据它们过于频繁地查询。
【讨论】:
首先放置trans_id
会使索引不可用。并且它与PRIMARY KEY(trans_id)
是冗余的,这(在 InnoDB 中)意味着数据是一个大的 BTree,首先用 trans_id 组织。【参考方案2】:
A计划
从任何WHERE
子句开始,即col = constant
。然后继续一件事。
建议你添加以下两个,因为不容易预测哪个会更好:
INDEX(acct_id, status_id, transaction_type)
INDEX(acct_id, status_id, trans_datetime)
B计划
SELECT
列表中真的只有 trans_id
吗?如果是这样,那么将其变成“覆盖”索引应该不错。这是一个索引,其中整个操作都可以在索引所在的 BTree 中执行,从而避免进入数据。
要构建这样的,首先构建最佳的非覆盖索引,然后在查询中添加 anywhere 中提到的其余字段。这些中的任何一个都应该工作:
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
。
【讨论】:
以上是关于MySQL如何创建正确的索引的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点# MySQL性能优化:如何高效正确的使用索引