MySQL 5.6,64位,RHEL 5.8
使用ORDER BY和LIMIT'row_count'(或LIMIT 0,'row_count')查询大型表。如果'row_count'较大,那么结果集的实际计数将非常慢。
案例1:下面的查询非常快(没有'限制'):
mysql> SELECT * FROM syslog WHERE
(ReportedTime BETWEEN '2013-11-04' AND '2013-11-05') AND
Priority<3 AND Facility=1 ORDER BY id DESC;
+---
| ...
6 rows in set (0.01 sec)
案例2:下面的查询也很快('LIMIT 5'):
mysql> SELECT * FROM syslog WHERE
(ReportedTime BETWEEN '2013-11-04' AND '2013-11-05') AND
Priority<3 AND Facility=1 ORDER BY id DESC LIMIT 5;
+---
| ...
5 rows in set (0.42 sec)
案例3:下面的查询非常慢('LIMIT 7',可以使用任何'row_count'值&gt; 6):
mysql> SELECT * FROM syslog WHERE
(ReportedTime BETWEEN '2013-11-04' AND '2013-11-05') AND
Priority<3 AND Facility=1 ORDER BY id DESC LIMIT 7;
+---
| ...
6 rows in set (28 min 7.24 sec)
差异只是个人(无限制),“限制5”和“限制7”。
为什么案例3这么慢?
案例3中的一些调查:
SELECT id FROM syslog ....
),但结果相同。BETWEEN '2013-10-03' to '2013-11-05'
以获得结果行数 149 。使用LIMIT 140
,速度很快。使用LIMIT 150
,它非常慢。太奇怪了。目前在我们的网站上,该程序首先获得实际结果行计数(SELECT COUNT(*) FROM ...
,No ORDER BY,No LIMIT),然后使用LIMIT'row_count'值进行查询,但不超过真正的行数刚刚到了。难看。
案例3的EXPLAIN:
-+-----..-+----..+-------+-----..+--------+---------+-----+-----+------------+
| sele.. | table| type | poss..| key | key_len | ref | rows| Extra |
-+-----..-+----..+-------+-----..+--------+---------+-----+-----+------------+
| SIMPLE | syslo| index | ... | PRIMARY| 8 | NULL| 132 | Using where|
-+-----..-+----..+-------+-----..+--------+---------+-----+-----+------------+
1 row in set (0.00 sec)
表格定义:
CREATE TABLE syslog (
id BIGINT NOT NULL AUTO_INCREMENT,
ReceivedAt TIMESTAMP NOT NULL DEFAULT 0,
ReportedTime TIMESTAMP NOT NULL DEFAULT 0,
Priority SMALLINT,
Facility SMALLINT,
FromHost VARCHAR(60),
Message TEXT,
InfoUnitID INT NOT NULL DEFAULT 0,
SysLogTag VARCHAR(60) NOT NULL DEFAULT '',
PRIMARY KEY (id),
KEY idx_ReportedTime_Priority_id (ReportedTime,Priority,id),
KEY idx_Facility (Facility),
KEY idx_SysLogTag (SysLogTag(16)),
KEY idx_FromHost (FromHost(16))
);
答案 0 :(得分:5)
Mysql因其在ORDER BY DESC + LIMIT
子句中的行为而闻名。
请参阅:http://www.mysqlperformanceblog.com/2006/09/01/order-by-limit-performance-optimization/
请尝试:
SELECT *
FROM syslog FORCE INDEX (Facility)
WHERE
ReportedTime BETWEEN '2013-11-04' AND '2013-11-05'
AND Priority<3
AND Facility=1
ORDER BY id DESC
LIMIT 7;
您需要强制使用第一个查询中使用的索引。 (从他们的解释计划中得到它,KEY专栏)