简体   繁体   English

使用 join 和 group by 子句选择查询中的 MySQL 性能问题

[英]MySQL performance issue in select query with join and group by clause

I am facing performance issue when querying a table with approx 700,000 records.查询包含大约 700,000 条记录的表时,我面临性能问题。 The query takes more than 10 seconds execute for the first time for a specific item_id, if I change the item_id value in the query the query takes nearly the same amount of time to execute.对于特定的 item_id,第一次执行查询需要超过 10 秒,如果我更改查询中的 item_id 值,则查询需要几乎相同的时间来执行。 However, subsequent query for the same item_id is fast unless the server is restarted.但是,除非重新启动服务器,否则对相同 item_id 的后续查询会很快。

The query I am trying to execute is -我试图执行的查询是 -

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

My table (InnoDB) structure is -我的表(InnoDB)结构是 -

Table: transaction_item (No primary Key, INDEX: item_id, Contains approx 700,000 rows)表:transaction_item(无主键,INDEX:item_id,包含约 700,000 行)

在此处输入图片说明

Table transaction_customer (Primary Key: invoice_id, contains approx 100,000 rows)表 transaction_customer(主键:invoice_id,包含约 100,000 行) 在此处输入图片说明

Running explain on the above query gives the following output:在上述查询上运行解释给出以下输出:

在此处输入图片说明

my.ini config my.ini 配置

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

Any help on fine tuning MySQL config/db schema will be highly appreciated.任何关于微调 MySQL 配置/数据库架构的帮助将不胜感激。

Your indexing isn't too bad for the query you have described.对于您描述的查询,您的索引编制还不错。 What is harming your performance is both of these tables have a significant amount of data in each row.损害您的性能的是这两个表在每一行中都有大量数据。 The query needs elements from each table that isn't in the secondary index and therefore large chunks for the table relevant to the specified item need to be in the innodb buffer pool.查询需要每个表中不在二级索引中的元素,因此与指定项目相关的表的大块需要在 innodb 缓冲池中。 I haven't looked at the exact numbers however 1G doesn't seem to be enough and your descriptions of the query becoming quicker the second time seem to support this (especially with SQL_NO_CACHE and the query cache disabled (good that its disabled).我没有查看确切的数字,但是 1G 似乎还不够,您对第二次查询变得更快的描述似乎支持这一点(尤其是在SQL_NO_CACHE和查询缓存禁用的情况下(很好,它被禁用)。

Recommendation 1: Increase the innodb_buffer_pool size.建议 1:增加innodb_buffer_pool大小。 Look at SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool%' and look at the number of items purged from the buffer between queries.查看SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool%'并查看在查询之间从缓冲区清除的项目数。

If you are really stuck with the RAM available, and following the theme of @Drapp recommendations on indexes, will allow for a innodb buffer pool to be used with only indexes rather than the complete table.如果您真的坚持可用的 RAM,并遵循 @Drapp 对索引的建议主题,将允许仅将 innodb 缓冲池用于索引而不是完整的表。 This innodb_buffer_pool is being competed against by other queries so the following have limited global impact.此 innodb_buffer_pool 正在与其他查询竞争,因此以下内容的全局影响有限。

Recommendation 2: (if #1 cannot be done)建议 2:(如果 #1 无法完成)

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);

Note: Removed sorting, was necessary for GROUP BY .注意:删除了排序,这是GROUP BY所必需的。 Thanks Rick谢谢瑞克

Formatted query for readability, but also added aliasing so someone in the future does not have to guess which columns come from which table.格式化查询以提高可读性,但还添加了别名,以便将来有人不必猜测哪些列来自哪个表。

Anyhow, to help optimize the query, you need a composite index to help the where, join and order by.无论如何,为了帮助优化查询,您需要一个复合索引来帮助 where、join 和 order by。

I would create an index on your Transaction_Item table on (item_id, item_rate_id, invoice_id )我会在您的 Transaction_Item 表上创建一个索引 (item_id, item_rate_id, invoice_id )

Also, on your Transaction_Customer table, have an index on (Invoice_id, Invoice_Type )此外,在您的 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM