mysql - 为什么从 MYSQL 中提取行的最后一部分(LIMIT 和 OFFSET)比提取所有其他部分要慢得多?
问题描述
我必须从数据库(MYSQL MariaDB)中提取相当大的数据块,因此我决定将其分成小块(限制 = 1000 行)。总的来说,我需要提取 ~9228 行(听起来不多,但当我尝试通过一个查询一次获取所有 9228 行时,获取时间达到 100 - 120 秒)。
当我获取前 8 个数据块(每个 1000 行)时,每个查询都很好 ~0.4 秒。但是,当我尝试提取最后 228 行时,一切都变得非常慢 - 如果我使用 80 秒,LIMIT 1000 OFFSET 9000
或者当我使用 LIMIT 的确切行数时为 50 秒LIMIT 228 OFFSET 9000
。但是用于获取总行数的查询需要 30 秒,因此两次查询总共需要 80 秒。
我获取数据的 sql 查询如下所示:
SELECT events.eventid, functions.triggerid FROM events
INNER JOIN functions ON events.objectid = functions.triggerid
WHERE
events.name LIKE 'DISCONNECT MSK-AP%'
OR events.name LIKE 'AP MSK-AP%' # '%MSK-AP%' is much slower than OR
AND events.value = 1
AND events.clock >= '1588280400'
AND events.clock <= '1590958799'
GROUP BY events.eventid
ORDER BY events.eventid DESC
LIMIT 1000 OFFSET 0; # SO OFFSET COULD BE 0, 1000, 2000, ... 8000, 9000
我获取总行数的 sql 查询(慢了 30 秒!)如下:
SELECT COUNT(distinct(events.eventid)) FROM events
INNER JOIN functions ON events.objectid = functions.triggerid
WHERE
events.name LIKE 'DISCONNECT MSK-AP%'
OR events.name LIKE 'AP MSK-AP%'
AND events.value = 1
AND events.clock >= '1588280400'
AND events.clock <= '1590958799';
我的数据库版本:
protocol_version 10 slave_type_conversions
version 5.5.60-MariaDB version_comment MariaDB Server version_compile_machine x86_64 version_compile_os Linux
为什么获取最后一个块的最后一个查询与其他查询相比如此缓慢,我能做些什么来解决这个问题?临时数据库表可以在这种情况下提供帮助吗?
为什么我不确定问题的答案是否适合我的情况: 为什么 MYSQL 更高的 LIMIT 偏移会减慢查询速度?
因为问题与偏移大小无关,例如:
LIMIT 100 OFFSET 9100;
- 0.25 秒但
LIMIT 100 OFFSET 9200;
- 114 秒!
因此,当 offset + limit 接近或大于总行数(9228)时,就会出现问题!
解决方案
OFFSET
糟糕的表现。
更好的方法是“记住你离开的地方”。
讨论:http: //mysql.rjweb.org/doc.php/pagination
为什么比全读慢?
使用OFFSET
时,查询首先计算 给出的行数OFFSET
,然后传递 给出的行数LIMIT
。所以,它变得越来越慢。最终偏移量与读取整个表所花费的时间大致相同。
推荐阅读
- elasticsearch - 按字段的未知值过滤文档
- php - Yii2 select2 数据库异常绑定变量数与令牌数不匹配
- r - 如何计算R中数据框中的条件平均值?
- c++ - 通过模板参数 C++ 将值传递给内部类
- php - 没有 session.auto_start=1 的 Symfony 无法登录
- wordpress - 发出 HTTP POST 请求以在 Wordpress 中上传文件 - HTTP POST 请求被转换为 GET
- javascript - 使弹出模式对话框出现后可移动/可拖动
- javascript - 使用 WebRTC 创建视频聊天应用程序的问题
- python - 如何在复合实体中使用从其他实体产生的字典?
- java - Quartz 调度器执行一个 Runnable