mysql - 优化 MySQL 中的 ORDER BY 和 LIMIT 查询

标签 mysql query-optimization

我尝试像这样优化查询:

SELECT sql_no_cache t.topic_id 
FROM   blog AS b, 
       topic AS t 
WHERE  t.topic_publish = 1 
       AND t.topic_type <> 'topic' 
       AND t.topic_lang = 'en' 
       AND t.blog_id = b.blog_id 
ORDER  BY t.topic_date_add DESC 
LIMIT  50;

架构:

CREATE TABLE `topic` (
  `topic_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `blog_id` int(11) unsigned NOT NULL,
  `user_id` int(11) unsigned NOT NULL,
  `topic_type` enum('topic_catalog','topic','link','question','photoset') NOT NULL DEFAULT 'topic',
  `topic_lang` varchar(16) NOT NULL DEFAULT 'russian',
  `topic_title` varchar(200) NOT NULL,
  `topic_date_add` datetime NOT NULL,
  `topic_date_edit` datetime DEFAULT NULL,
  `topic_publish` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`topic_id`),
  UNIQUE KEY `topic_date_add`     (`topic_type`,`topic_lang`,`topic_publish`,`blog_id`,`topic_id`,`topic_date_add`),
  KEY `blog_id` (`blog_id`),
  KEY `user_id` (`user_id`),
  KEY `topic_date_add` (`topic_date_add`,`topic_type`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

topic包含大约1M记录,并且在没有ORDER BY的情况下工作得很好(大约0.0016s)。

使用 ORDER BY t.topic_date_add DESC 查询执行时间要长得多(在同一台计算机上大约为 2.8083)

解释使用order查询如下:

+----+-------------+-------+--------+----------------------+----------------+---------+--------------------+------+-------------+
| id | select_type | table | type   | possible_keys        | key            | key_len | ref                | rows | Extra       |
+----+-------------+-------+--------+----------------------+----------------+---------+--------------------+------+-------------+
|  1 | SIMPLE      | t     | index  | blog_id,topic_rating | topic_date_add | 9       | NULL               |   50 | Using where |
|  1 | SIMPLE      | b     | eq_ref | PRIMARY,blog_type    | PRIMARY        | 4       | sku_prod.t.blog_id |    1 | Using where |
+----+-------------+-------+--------+----------------------+----------------+---------+--------------------+------+-------------+

我是查询优化方面的新手,不明白为什么带排序的查询执行这么长时间。从 Explain 看来只执行了 50 行。

因此,我们很高兴听到有关优化此查询的任何想法。如果需要,我可以添加任何缺失的信息。

最佳答案

首先,学习使用正确、明确的 JOIN 语法:

SELECT sql_no_cache t.topic_id 
FROM blog b JOIN
     topic t
     ON t.blog_id = b.blog_id
WHERE t.topic_publish = 1 
      t.topic_type <> 'topic' 
      t.topic_lang = 'en'  
ORDER BY t.topic_date_add DESC 
LIMIT 50;

对于此查询,最佳索引为 topic(topic_lang, topic_publish, topic_type, blog_id, topic_date_add, topic_id)。最后两个键不会用于排序,但包含它们会使索引成为覆盖索引。

假设 blog_id 始终与 blog 中的内容匹配,那么为什么不直接使用:

SELECT sql_no_cache t.topic_id 
FROM topic t
WHERE t.topic_publish = 1 
      t.topic_type <> 'topic' 
      t.topic_lang = 'en'  
ORDER BY t.topic_date_add DESC 
LIMIT 50;

相同的索引适用于此。

关于mysql - 优化 MySQL 中的 ORDER BY 和 LIMIT 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39947890/

相关文章:

mysql - 如何优化这个 MYSQL 查询?

php - 由于遇到错误,该网站目前处于离线状态 - Mautic

php - 使用准备好的语句进行 SQL 注入(inject)

mysql - 我登录了 phpmyadmin。登录后我收到错误。

mysql - 获取查询中先前记录的总和并添加或减去以下结果

sql - 当您有大量桥接表时测量单个或多个查询的性能

mysql - 我有哪些选择可以使我的 ORDER BY 更快?

mysql - 教义2 : Different behaviours on removing and persisting related Entities

MySQL 语句

SQL Server : IF EXISTS massively slowing down a query