如何增强对数百万行表的 MySQL 查询?
Posted
技术标签:
【中文标题】如何增强对数百万行表的 MySQL 查询?【英文标题】:How to boost MySQL query on tables with millions of rows? 【发布时间】:2021-06-06 20:51:26 【问题描述】:我的数据库中有 2 个大表(wp_frm_items
大约有 300 万行,wp_frm_item_metas
大约有 3500 万行)。
我正在使用 Query Monitor WordPress 插件,并注意到使用连接和计数的查询很慢。
有些查询需要 8 秒以上才能完成!我通过添加DISTINCT
解决了这个问题,以便将查询执行时间减少到大约 2 秒!
但是触发查询的页面完全加载仍然有点慢。
查询监视器检测到我有 3 个慢查询。
1.6813s
SELECT DISTINCT it.item_id
FROM wp_frm_item_metas it
LEFT OUTER JOIN wp_frm_fields fi
ON it.field_id=fi.id
INNER JOIN wp_frm_items e
ON (e.id=it.item_id)
WHERE fi.id=110
AND ( it.meta_value='jack' )
2.7120s
SELECT COUNT(*)
FROM wp_frm_items it
LEFT OUTER JOIN wp_frm_forms fr
ON it.form_id=fr.id
1.1344s
SELECT id
FROM wp_frm_items
WHERE form_id=10
我在查询中使用的所有列上都添加了索引 (BTREE),但查询仍然很慢!我正在使用InnoDB
。
如何在我的场景中优化查询执行时间?
我读过这篇文章https://www.percona.com/blog/2007/11/01/innodb-performance-optimization-basics,关于调整一些参数,如innodb_buffer_pool_size=50G
(大约80% 的服务器64GB RAM)、innodb_flush_log_at_trx_commit=2
和innodb_flush_method=O_DIRECT
,但是使用这些参数查询会变得更慢!
如何知道调整InnoDB
性能的最佳值是多少?
这是我当前的/etc/my.cnf
文件:
[mysqld]
innodb_file_per_table=1
default-storage-engine=InnoDB
performance-schema=0
max_allowed_packet=268435456
open_files_limit=40000
secure-file-priv = ""
【问题讨论】:
meta_value 属于表 wp_frm_item_metas (it)。我已经更新了问题 顺便提一下,DISTINCT 不太可能提高查询速度。如果您想要 DISTINCT 行而不是为了提高性能,请使用 DISTINCT。 这些表来自Formidable Form Builder 插件。 从与您提到的一样大的表中,您的第一个和第三个查询可能会返回非常大的结果集。在索引或缓冲区大小方面没有任何魔法可以加快速度。第二个查询有类似的问题。它会计算您所有表单的确切回复总数。数数需要时间。最好的办法是询问插件开发人员如何在导出旧响应后删除它们以缩小表格。 【参考方案1】:将您的查询修改为:
SELECT DISTINCT it.item_id
FROM wp_frm_item_metas it
JOIN wp_frm_fields fi
ON it.field_id = fi.id
JOIN wp_frm_items e
ON e.id = it.item_id
WHERE fi.id = 110
AND it.meta_value = 'jack'
并删除除 PRIMARY KEY 之外的所有索引,并在 (it.field_id,it.item_id,it.meta_value) 的某些组合上添加复合索引;
【讨论】:
这可能需要在 it.meta_value 上建立一个索引,fi.id 可能是一个 PK,使用 exists() 而不是 join 可能会更好。但这是猜测,因为 OP 没有包含任何架构,【参考方案2】:请为每张桌子提供SHOW CREATE TABLE
。
如果wp_frm_items
有INDEX(form_id)
,最后一个查询可能会受益
【讨论】:
以上是关于如何增强对数百万行表的 MySQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章