带有连接和group by子句的选择查询中的MySQL性能问题

问题描述 投票:0回答:2

查询约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行)

enter image description here

表transaction_customer(主键:invoice_id,包含大约100,000行)enter image description here

上面查询的运行说明给出了以下输出:

enter image description here

my.ini配置

[mysqld]
query_cache_size=0
query_cache_type=0
innodb_buffer_pool_size = 1G

高度赞赏有关微调MySQL config / db模式的任何帮助。

mysql query-performance
2个回答
0
投票

格式化的可读性查询,但也添加了别名,因此将来的某人不必猜测哪个列来自哪个表。

无论如何,为了帮助优化查询,您需要一个复合索引来帮助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

0
投票

请注意您的解释中的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);
© www.soinside.com 2019 - 2024. All rights reserved.