优化慢查询MySQL InnoDB(Doctrine2)

时间:2012-05-21 07:13:24

标签: mysql sql-order-by innodb database-performance

我在使用Doctrine2的Symfony2项目中查询速度慢。我不确定是什么减慢了这一点。我试图自己追踪它,但已经没有想法了。基本的想法是我想从给定的Feed中获取前20篇文章(按ID)并按发布日期对它们进行排序。当我在我的开发机器上排序大约300篇文章(生产机器有数千种)时,似乎1秒钟有点长。

查询是:

SELECT 
    a0_.id AS id0, a0_.guid AS guid1, a0_.title AS title2, a0_.pub_date AS pub_date3,
    a0_.summary AS summary4, a0_.content AS content5, a0_.source_url AS source_url6,
    a0_.comment_url AS comment_url7, a0_.slug AS slug8, a0_.bitly_url AS bitly_url9,
    a0_.thumbnail_id AS thumbnail_id10, a0_.feed_id AS feed_id11,
    a0_.author_id AS author_id12
FROM
    articles a0_ 
WHERE 
    a0_.feed_id = ?
ORDER BY  
    a0_.pub_date DESC LIMIT 20

Parameters: ['19']
Time: 958.46 ms

运行EXPLAIN,我明白了:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: a0_
         type: ref
possible_keys: feed_guid,article_slug_unique,feed
          key: feed_guid
      key_len: 4
          ref: const
         rows: 338
        Extra: Using where; Using filesort
1 row in set (0.11 sec)

这是我的表:

+--------------+------------------+------+-----+---------+----------------+
| Field        | Type             | Null | Key | Default | Extra          |
+--------------+------------------+------+-----+---------+----------------+
| id           | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| guid         | varchar(255)     | NO   |     | NULL    |                |
| title        | varchar(255)     | NO   |     | NULL    |                |
| author_id    | int(10) unsigned | YES  | MUL | NULL    |                |
| pub_date     | datetime         | YES  | MUL | NULL    |                |
| summary      | text             | YES  |     | NULL    |                |
| content      | text             | NO   |     | NULL    |                |
| source_url   | varchar(255)     | YES  |     | NULL    |                |
| comment_url  | varchar(255)     | YES  |     | NULL    |                |
| feed_id      | int(10) unsigned | NO   | MUL | NULL    |                |
| slug         | varchar(64)      | NO   | MUL | NULL    |                |
| bitly_url    | varchar(32)      | YES  |     | NULL    |                |
| thumbnail_id | int(10) unsigned | YES  | UNI | NULL    |                |
+--------------+------------------+------+-----+---------+----------------+
13 rows in set (0.09 sec)

我的指数:

+----------+------------+-----------------------+--------------+--------------+----------+-------------+----------+--------+------+------------+---------+---------------+
| Table    | Non_unique | Key_name              | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+----------+------------+-----------------------+--------------+--------------+------------------------+----------+--------+------+------------+---------+---------------+
| articles |          0 | PRIMARY               |            1 | id           | A         |       51479 |     NULL | NULL   |      | BTREE      |         |               |
| articles |          0 | feed_guid             |            1 | feed_id      | A         |         352 |     NULL | NULL   |      | BTREE      |         |               |
| articles |          0 | feed_guid             |            2 | guid         | A         |         352 |     NULL | NULL   |      | BTREE      |         |               |
| articles |          0 | article_slug_unique   |            1 | feed_id      | A         |         352 |     NULL | NULL   |      | BTREE      |         |               |
| articles |          0 | article_slug_unique   |            2 | slug         | A         |         352 |     NULL | NULL   |      | BTREE      |         |               |
| articles |          0 | UNIQ_BFDD3168FDFF2E92 |            1 | thumbnail_id | A         |       51479 |     NULL | NULL   | YES  | BTREE      |         |               |
| articles |          1 | author                |            1 | author_id    | A         |        3677 |     NULL | NULL   | YES  | BTREE      |         |               |
| articles |          1 | feed                  |            1 | feed_id      | A         |        1660 |     NULL | NULL   |      | BTREE      |         |               |
| articles |          1 | slug_idx              |            1 | slug         | A         |       51479 |     NULL | NULL   |      | BTREE      |         |               |
| articles |          1 | pub_date_idx          |            1 | pub_date     | A         |       51479 |     NULL | NULL   | YES  | BTREE      |         |               |
+----------+------------+-----------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
10 rows in set (0.68 sec)

如果有帮助,这里是Doctrine2代码:

$dql = $this->getEntityManager()
        ->createQueryBuilder()
        ->select('art')
        ->from('MyMainBundle:Article', 'art')
        ->where('art.feed = :f_id')
        ->orderBy('art.pubDate', 'DESC');

我认为必须有某种方法让MySQL使用我的pub_date_idx索引来订购记录。我特意添加了索引,因为我认为我已经读过,索引应该用于ORDER BY中使用的列。请帮助我改进此查询性能。

1 个答案:

答案 0 :(得分:1)

这个查询应该有(feed,pubDate)的索引来使用索引。如果你把它放在一边就可以解决:

CREATE INDEX idx_feed_pub_date ON articles (feed_id, pub_date)