考虑下表及其索引:
CREATE TABLE 'Interaction' ( 'oid' bigint(20) NOT NULL, 'archieved' datetime DEFAULT NULL, 'content' longtext COLLATE utf8_bin, 'contentSentiment' int(11) DEFAULT NULL, 'createdAt' datetime DEFAULT NULL, 'id' varchar(255) COLLATE utf8_bin DEFAULT NULL, 'interactionSource' longtext COLLATE utf8_bin, 'link' varchar(255) COLLATE utf8_bin DEFAULT NULL, 'source' varchar(255) COLLATE utf8_bin DEFAULT NULL, 'title' varchar(255) COLLATE utf8_bin DEFAULT NULL, 'type' int(11) DEFAULT NULL, 'authorKloutScore' int(11) DEFAULT NULL, PRIMARY KEY ('oid'), KEY 'createdAt' ('createdAt'), KEY 'fullMonitorFeedSearch' ('criteria_oid','createdAt','authorKloutScore','archieved','type') ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin
如果存在覆盖它的索引(fullMonitorFeedSearch),为什么以下查询运行缓慢?顺便说一句,如果删除'interactio0_.TYPE = 2',sql将在0.01秒内运行。
SELECT interactio0_.oid FROM Interaction interactio0_ WHERE interactio0_.criteria_oid = 21751021 AND interactio0_.createdat = 10 AND interactio0_.archieved IS NULL AND interactio0_.TYPE = 2 ORDER BY interactio0_.createdat DESC
这是sql的解释:
+----+-------------+--------------+-------+--------------------------------------------------------------------------+-----------------------+---------+------+---------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------------+-------+--------------------------------------------------------------------------+-----------------------+---------+------+---------+-------------+ | 1 | SIMPLE | interactio0_ | range | FKD15475F24AA96F7,createdAt,fullMonitorFeedSearch | fullMonitorFeedSearch | 18 | NULL | 2323027 | Using where | +----+-------------+--------------+-------+--------------------------------------------------------------------------+-----------------------+---------+------+---------+-------------+
答案 0 :(得分:1)
似乎MySQL可能无法完全使用索引,因为索引中的列与WHERE中使用的列不同,也不是相同的顺序。尝试从索引中删除列authorKloutScore
:
fullMonitorFeedSearch
(criteria_oid
,type
,createdAt
,archieved
)
然后将查询修改为:
SELECT interactio0_.oid
FROM Interaction interactio0_
WHERE interactio0_.criteria_oid = 21751021
AND interactio0_.type = 2
AND interactio0_.createdat = 10
AND interactio0_.archieved IS NULL
ORDER BY interactio0_.createdat DESC;
一些额外的建议/关注点:
如果type
列应包含1,2,3等值,我认为将其重新声明为TINYINT UNSIGNED是有意义的。这应该允许您存储0到255范围内的值。
类似的建议authorKloutScore
和contentSentiment
列重新声明为TINYINT UNSIGNED或SMALLINT UNSIGNED,具体取决于列可能包含的值。
索引和查询提到了列criteria_oid
,但表定义中缺少该列。我不确定它是否是拼写错误或列不存在。
createdAt
列是DATETIME,但查询中相应的WHERE谓词没有多大意义 - interactio0_.createdat = 10
。不应该是右侧的日期或日期时间值。或者该列是否仅用于存储特定数据(日,月或小时)?
查询中的一个特定条件是interactio0_.criteria_oid = 21751021
。正如我上面提到的,表定义中缺少该列。但是,这里的想法是,如果该列是UNIQUE,则删除所有其他WHERE条件更有意义 - 选择记录criteria_oid = 21751021
并在PHP中的结果集中执行其他检查。但是,如果列不是UNIQUE并且可能有许多行具有相同的creative_oid
,那么查询就可以了。
希望以上有所帮助!
答案 1 :(得分:0)
这可能是基数的问题;如果为Type单独创建特定索引会发生什么?
另外,考虑一下您的数据场景,更有可能的是 - 创建的是特定的还是被取消的是空的?
优化索引时的主要考虑因素之一是考虑数据的常见程度;也就是说,如果你在4个字段上建立索引并且可以选择一个计数,按这4个字段进行分组,如果你得到了大量的记录,那么你的索引是错误的。