简体   繁体   中英

Very slow simple sql query

I have 5 tables in InnodDB, and they have in sum ~ 40million records

I want create simple filter for search contact_id with all tables.

To do this, I create the following query:

SELECT c.id FROM contacts AS c 
JOIN bonus_cards AS B USING(client_id) 
JOIN orders AS o USING(card_number) 
JOIN order_items AS oi USING (order_id) 
JOIN products AS p USING (product_id) WHERE p.brand_id = 125; 

I also used a different query style:

SELECT c.id FROM contacts AS c 
INNER JOIN bonus_cards AS bc ON(bc.client_id=c.client_id) 
INNER JOIN orders AS o ON(bc.card_number=o.card_number) 
INNER JOIN order_items AS oi ON(o.order_id=oi.order_id) 
INNER JOIN products AS p ON(oi.product_id=p.product_id) WHERE p.brand_id = 125;

There is no difference in time.

The request is very long. And for a very long time it's more than 30 minutes.

I have all the necessary indices, and when I do the query query, I see that the indexes are involved.

My config my.cnf:

    net_read_timeout = 3600
    net_write_timeout = 3600
    wait_timeout = 120
    interactive_timeout = 120
    key_buffer_size =32M
    sort_buffer_size = 8M
    max_allowed_packet = 1M
    read_rnd_buffer_size = 1M
    thread_stack = 128K
    query_cache_limit = 1M
    query_cache_size = 0
    query_cache_type = 1
    thread_cache_size = 16
    max_heap_table_size = 128M
    tmp_table_size = 128M
    innodb_open_files = 4096
    innodb_file_per_table = 1
    innodb_flush_method=O_DIRECT
    innodb_flush_log_at_trx_commit=0
    innodb_log_file_size = 128M
    innodb_log_buffer_size = 16M
    innodb_buffer_pool_size=2048M
    innodb_buffer_pool_instances=1
    #innodb_additional_mem_pool_size = 16M
    innodb_thread_concurrency = 16
    innodb_read_io_threads = 8
    innodb_write_io_threads = 8
    innodb_stats_on_metadata = 0
    innodb_data_file_path=ibdata1:10M:autoextend

For this query:

SELECT c.id
FROM contacts AS c JOIN 
     bonus_cards AS B USING(client_id) JOIN 
     orders AS o USING(card_number) JOIN
     order_items AS oi USING (order_id) JOIn
     products AS p USING (product_id)
WHERE p.brand_id = 125; 

The optimal indexes are:

  • products(brand_id, product_id)
  • order_items(product_id, order_id)
  • orders(order_id, card_number)
  • bonus_cards(card_number, client_id)
  • contacts(client_id, id)

That said, I'm surprised that you have to go through a table such as bonus_cards to tie an order to a contact.

I found bug in db structure. I'm working with a database that I was given and I did not have any changes in its integrity.

But the phrase - never believe the data, turned out to be true. The database was not the correct data types that linked the subtables.

For example:

contacts - client_id int 8 not null,
bonus_cards - client_id int 8 not null,
bonus_cards - card_number varchar 56 not null,
orders - card_number varchar 56 not null,
orders - order_id int 11 not null,
order_items order_id **varchar 50** not null,
order_items product_id **varchar 50** not null,
products product_id int 8 not null,
products brand_id int 8 not null,

I probably gave one more example, which may arise from the developers. First of all, when debugging queries, check with the data type.

I hope I helped the community.

PS Speed of query execution 5s (8.2Gb database and 2gb RAM) :) easy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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