带有连接和group by子句的选择查询中的MySQL性能问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带有连接和group by子句的选择查询中的MySQL性能问题相关的知识,希望对你有一定的参考价值。
查询约700,000条记录的表时,我面临性能问题。对于特定的item_id,查询首次执行将花费10秒钟以上的时间,如果我更改查询中的item_id值,则查询将花费几乎相同的时间来执行。但是,除非重新启动服务器,否则后续查询相同的item_id的速度很快。
我要执行的查询是-
select SQL_NO_CACHE item_id, item_rate_id, invoice_type, sum(qty_computed) as qty
from transaction_item
left join transaction_customer
on transaction_item.invoice_id = transaction_customer.invoice_id
where item_id = 17179
group by item_rate_id, invoice_type
我的表(InnoDB)的结构是-
表:transaction_item(无主键,索引:item_id,包含大约700,000行)
表transaction_customer(主键:invoice_id,包含大约100,000行)
上面查询的运行说明给出了以下输出:
my.ini配置
[mysqld]
query_cache_size=0
query_cache_type=0
innodb_buffer_pool_size = 1G
高度赞赏有关微调MySQL config / db模式的任何帮助。
格式化的可读性查询,但也添加了别名,因此将来的某人不必猜测哪个列来自哪个表。
无论如何,为了帮助优化查询,您需要一个复合索引来帮助where,join和order by。
我将在(item_id,item_rate_id,invoice_id)在您的Transaction_Item表上创建索引
此外,在您的Transaction_Customer表上,在(Invoice_id,Invoice_Type)上有一个索引
select SQL_NO_CACHE
ti.item_id,
ti.item_rate_id,
tc.invoice_type,
sum(ti.qty_computed) as qty
from
transaction_item ti
left join transaction_customer tc
on ti.invoice_id = tc.invoice_id
where
ti.item_id = 17179
group by
ti.item_rate_id,
tc.invoice_type
请注意您的解释中的using filesort
。我认为这是因为您使用的MySQL版本低于8.0。在这些版本中,结果由GROUP BY
子句隐含地排序,大约为2500行。这会增加少量查询时间。
建议1:在查询中添加ORDER BY NULL以删除排序。
您的索引对于您描述的查询来说还不错。损害您的性能的是,这两个表的每一行都有大量数据。该查询需要来自每个表的元素,这些元素不在二级索引中,因此与指定项目相关的表的大块数据必须位于innodb缓冲池中。我没有看确切的数字,但是1G似乎还不够,您对查询的描述第二次变得更快似乎支持了这一点(尤其是在SQL_NO_CACHE
和查询缓存被禁用的情况下(很好的是,它被禁用了) 。
建议2:增大innodb_buffer_pool
的大小。查看SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool%'
,然后查看两次查询之间从缓冲区清除的项目数。
如果您确实对可用的RAM感到困惑,并遵循索引上@Drapp建议的主题,将允许仅将索引而不是整个表用于innodb缓冲池。此innodb_buffer_pool正在与其他查询竞争,因此以下内容对全局影响有限。
建议3 :(如果无法完成#2)
ALTER TABLE transaction_item
DROP INDEX item_id
ADD INDEX item_id (item_id, item_rate_id, qty_computed );
ALTER TABLE transaction_customer
ADD INDEX id_type (invoice_id, invoice_type);
以上是关于带有连接和group by子句的选择查询中的MySQL性能问题的主要内容,如果未能解决你的问题,请参考以下文章
我们如何在具有GROUP BY子句的查询中选择非聚合列,而GROUP BY子句在功能上不依赖于GROUP BY子句中的列?
如何从表中选择带有 oracle sql 中的 group by 子句的嵌套 json 对象?