【发布时间】:2019-07-14 10:05:59
【问题描述】:
我有一个很大的事件表。 (目前为 530 万行)。我需要以线性方式从头到尾遍历这个表。大多数情况下没有随机搜索。目前的数据包括大约 5 天的这些事件。
由于表格的大小,我需要对结果进行分页,互联网告诉我“寻求分页”是最好的方法。
但是,这种方法在前 3 天运行时效果很好,速度很快,之后 mysql 真的开始变慢了。我发现它一定是 io-bound,因为随着减速开始,我的 cpu 使用率实际上会下降。
我相信这与我所做的 2 列排序以及文件排序的使用有关,也许 Mysql 需要读取所有行来对我的结果进行排序或其他什么。正确索引可能是一个正确的解决方法,但我还没有找到解决我的问题的索引。
这个数据库的复杂部分是 id 和时间戳的顺序并不完美。该软件要求数据按时间戳排序。但是,在向该数据库添加数据时,某些事件是在实际发生后 1 分钟添加的,因此自动递增的 id 不是按时间顺序排列的。
截至目前,减速非常严重,以至于我为期 5 天的遍历从未完成。它只是变得越来越慢......
我尝试过以多种方式为表建立索引,但 mysql 似乎不想使用这些索引,并且 EXPLAIN 一直显示“filesort”。不过,索引用于 where 语句。
我目前使用的解决方法是首先进行全表遍历并将所有行 ID 和时间戳加载到内存中。我在软件的 python 端对行进行排序,然后在遍历时从 mysql 以较小的块加载完整数据(仅通过 ids)。这可以正常工作,但由于相同数据总共需要遍历 2 次,因此效率很低。
表的架构:
CREATE TABLE `events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`server` varchar(45) DEFAULT NULL,
`software` varchar(45) DEFAULT NULL,
`timestamp` bigint(20) DEFAULT NULL,
`data` text,
`event_type` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index3` (`timestamp`,`server`,`software`,`id`),
KEY `index_ts` (`timestamp`)
) ENGINE=InnoDB AUTO_INCREMENT=7410472 DEFAULT CHARSET=latin1;
查询(一个可能的行):
SELECT software,
server,
timestamp,
id,
event_type,
data
FROM events
WHERE ( server = 'a58b'
AND ( software IS NULL
OR software IN ( 'ASD', 'WASD' ) ) )
AND ( timestamp, id ) > ( 100, 100 )
AND timestamp <= 200
ORDER BY timestamp ASC,
id ASC
LIMIT 100;
查询基于https://blog.jooq.org/2013/10/26/faster-sql-paging-with-jooq-using-the-seek-method/(以及其他一些具有相同想法的帖子)。我相信它被称为“用搜索谓词搜索分页”。基本要点是我有一个开始时间戳和结束时间戳,我需要使用我指定的服务器上的软件获取所有事件,或者只获取特定于服务器的事件(软件 = NULL)。奇怪的()-东西是由于python根据给定的参数构造查询。如果它们可能会产生一些影响,我会让它们可见。
除了在宇宙热寂之前完成的遍历。
【问题讨论】:
-
我从未在 MySQL 中看到过这种结构:
(timestamp,id) > (100,100)。我测试了它,它做了一些事情,但我不知道是什么,也找不到任何文档。有谁能赐教吗? -
@KIKOSoftware 称为Row Subqueries 或元组比较。检查this 和this
-
@MadhurBhaiya 谢谢,是的,似乎就是这样。在不知道它叫什么的情况下很难找到它。我发现
(a, b) > (x, y)等价于(a > x) OR ((a = x) AND (b > y))。难怪我无法通过测试来弄清楚。 -
server和software的基数是多少(运行:select count(distinct server), count(distinct software) from events) -
请发布 A) SHOW INDEX FROM events 的 TEXT 结果;和 B) EXPLAIN SELECT SQL_NO_CACHE 软件、服务器、时间戳......我们将了解每个索引的基数,并了解 OPTIMIZER 可能对您的查询做什么。