Mysql 查询速度非常慢,以较大的限制范围排序

Mysql 查询速度非常慢,以较大的限制范围排序,mysql,sql,performance,optimization,Mysql,Sql,Performance,Optimization,MySQL 5.6,64位,RHEL 5.8 对具有ORDER BY和LIMIT“row\U count”(或LIMIT 0,“row\U count”)的大型表的查询。如果“行计数”大于结果集的实际计数,则速度将非常慢。 案例1:下面的查询非常快(没有“限制”): 表定义: CREATE TABLE syslog ( id BIGINT NOT NULL AUTO_INCREMENT, ReceivedAt TIMESTAMP NOT NULL DEFAUL

MySQL 5.6,64位,RHEL 5.8
对具有ORDER BY和LIMIT“row\U count”(或LIMIT 0,“row\U count”)的大型表的查询。如果“行计数”大于结果集的实际计数,则速度将非常慢。

案例1:下面的查询非常快(没有“限制”):

表定义:

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))
);

Mysql以其围绕
orderbydesc+LIMIT
子句的行为而闻名

见:

请尝试:

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;
选择*
来自syslog FORCE INDEX(设施)
哪里
报告时间介于“2013-11-04”和“2013-11-05”之间

首先,你是否也尝试过在
设施上建立索引?这是InnoDB还是MyISAM,甚至是Archive之类的东西?向我们展示查询的解释计划,这会占用更多的时间。这里的主要问题是,如果索引会影响查询,第一种和第二种情况也会变慢。正确的?极限6(快速)和极限7(非常慢)之间的巨大性能差异。解释说它只使用了主键。我在InnoDB和MyISAM中都尝试过。遇到同样的问题。我添加了
强制索引(idx\u ReportedTime\u Priority\u id)
。它很快就会恢复正常。我不知道MySQL的内部结构,为什么从
limit5
limit6
会有如此大的不同。非常感谢你。
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)
-+-----..-+----..+-------+-----..+--------+---------+-----+-----+------------+
 | 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))
);
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;