如何增强对数百万行表的 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=2innodb_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_itemsINDEX(form_id),最后一个查询可能会受益

【讨论】:

以上是关于如何增强对数百万行表的 MySQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

mysql中数百万行的基于键的分区

具有 10+ 百万行的 MySQL 表 - 如何使用索引加快搜索速度?

百万行超大csv如何快速导入mysql

从 100 万行表中优化插入最大日期

从 MySQL 查询中从百万行中选择第 N 条记录

对大型 MySQL 表的多个查询