我在 InnoDb item
表中有一个查询,其中包含 400k 条记录(仅...)。我需要对表示层的结果进行分页(每页 60 个),因此我使用 LIMIT
,其值取决于要显示的页面。
查询是(110000
偏移量只是一个例子):
SELECT i.id, sale_type, property_type, title, property_name, latitude,
longitude,street_number, street_name, post_code,picture, url,
score, dw_id, post_date
FROM item i WHERE picture IS NOT NULL AND picture != ''
AND sale_type = 0
ORDER BY score DESC LIMIT 110000, 60;
在我的机器上运行这个查询大约需要 1 秒。 在我们的测试服务器上运行此查询需要 45-50 秒。
EXPLAIN 都是一样的:
+----+-------------+-------+-------+---------------+-----------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+-----------+---------+------+--------+-------------+
| 1 | SIMPLE | i | index | NULL | IDX_SCORE | 5 | NULL | 110060 | Using where |
+----+-------------+-------+-------+---------------+-----------+---------+------+--------+-------------+
查询 show variables
时唯一的配置差异是:
innodb_use_native_aio
。它在测试服务器上启用,而不是在我的机器上启用。我尝试禁用它,但没有看到任何重大变化innodb_buffer_pool_size
1G 在测试服务器上,2G 在我的机器上
测试服务器有 2Gb 内存,2 核 CPU:
- mysqld 始终使用 > 65% 的 RAM,但在运行以上查询时仅增加 1-2%
- mysqld 在运行上述查询时使用了 14% 的 CPU,空闲时没有
我的本地机器有 8Gb,8 核 CPU:
- mysqld 始终使用 28% 的 RAM,并且在运行上述查询时并没有真正增加(或者在我能看到的这么短的时间内)
- mysqld 在运行上述查询时使用了 48% 的 CPU,空闲时没有
要在测试服务器上获得相同的性能,我在哪里可以做什么? RAM 和/或 CPU 是否太低?
更新
我设置了一个新的测试服务器,具有相同的规范,但 8G RAM 和 4 核 CPU,性能刚刚跃升至与我的机器相似的值。原来的服务器似乎没有使用所有的 RAM/CPU,为什么性能这么差?
最佳答案
破坏性能的最可靠方法之一是让 MySQL 扫描一个不适合内存的索引。因此在查询期间,它必须将索引的一部分加载到缓冲池中,然后逐出该部分并加载索引的另一部分。在查询期间像这样在缓冲池中造成搅动会导致大量 I/O 负载,这会使其非常慢。磁盘 I/O 比 RAM 慢大约 100,000 倍。
因此,1GB 缓冲池和 2GB 缓冲池之间存在很大差异,如果您的索引是 1.5GB。
另一个提示:您真的不想使用 LIMIT 110000, 60
。这导致 MySQL 从缓冲池中读取 110000 行(必要时可能从磁盘加载它们)只是为了丢弃它们。还有其他方法可以更有效地对结果集进行分页。
参见 Optimized Pagination using MySQL 等文章.
关于MySQL LIMIT x,y 在两台机器上的性能差异巨大,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16312119/