在mysql上运行缓慢的sql

时间:2011-07-19 01:37:29

标签: mysql sql indexing

考虑下表及其索引:

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 |
+----+-------------+--------------+-------+--------------------------------------------------------------------------+-----------------------+---------+------+---------+-------------+

2 个答案:

答案 0 :(得分:1)

似乎MySQL可能无法完全使用索引,因为索引中的列与WHERE中使用的列不同,也不是相同的顺序。尝试从索引中删除列authorKloutScore

fullMonitorFeedSearchcriteria_oidtypecreatedAtarchieved

然后将查询修改为:

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;

一些额外的建议/关注点:

  1. 如果type列应包含1,2,3等值,我认为将其重新声明为TINYINT UNSIGNED是有意义的。这应该允许您存储0到255范围内的值。

  2. 类似的建议authorKloutScorecontentSentiment列重新声明为TINYINT UNSIGNED或SMALLINT UNSIGNED,具体取决于列可能包含的值。

  3. 索引和查询提到了列criteria_oid,但表定义中缺少该列。我不确定它是否是拼写错误或列不存在。

  4. createdAt列是DATETIME,但查询中相应的WHERE谓词没有多大意义 - interactio0_.createdat = 10。不应该是右侧的日期或日期时间值。或者该列是否仅用于存储特定数据(日,月或小时)?

  5. 查询中的一个特定条件是interactio0_.criteria_oid = 21751021。正如我上面提到的,表定义中缺少该列。但是,这里的想法是,如果该列是UNIQUE,则删除所有其他WHERE条件更有意义 - 选择记录criteria_oid = 21751021并在PHP中的结果集中执行其他检查。但是,如果列不是UNIQUE并且可能有许多行具有相同的creative_oid,那么查询就可以了。

  6. 希望以上有所帮助!

答案 1 :(得分:0)

这可能是基数的问题;如果为Type单独创建特定索引会发生什么?

另外,考虑一下您的数据场景,更有可能的是 - 创建的是特定的还是被取消的是空的?

优化索引时的主要考虑因素之一是考虑数据的常见程度;也就是说,如果你在4个字段上建立索引并且可以选择一个计数,按这4个字段进行分组,如果你得到了大量的记录,那么你的索引是错误的。