0

this kind of MySQL-Query is very slow at the moment.

What would be the best indices for this to speed it up? (InnoDB)

SELECT item_id, 
       Group_concat(storage_nr SEPARATOR ',') AS storage_nr, 
       Group_concat(condition SEPARATOR ',') AS condition, 
       Group_concat(number SEPARATOR ',') AS number, 
       Group_concat(price SEPARATOR ',') AS price, 
       last_calc 
FROM   items
WHERE  number > 0 
       AND bottomlimit IS NOT NULL 
       AND condition IN (1, 2, 3) 
       AND ( price_date IS NULL 
              OR price_date < Date_sub(Now(), INTERVAL 1 hour) ) 
       AND ( NOT ( price = bottomlimit 
                   AND pricebefore = bottomlimit 
                   AND pricebefore2 = bottomlimit ) 
              OR price IS NULL 
              OR pricebefore IS NULL 
              OR pricebefore2 IS NULL 
              OR Date(price_date) <> Curdate() ) 
GROUP  BY item_id 
ORDER  BY last_calc 
LIMIT  20

Thanks a lot in advance!

Best regards!

Webbox
  • 25
  • 3

3 Answers3

0

I'm inclined to agree with Gordon's comment for the most part, but one thing you could try is conditional aggregation. (This could be one of those unique scenarios where processing more of the data and discarding what you don't need is faster than filtering to what you do need, especially since it seems some OR conditions tend to wreck index use in MySQL).

Something similar to this might help.

SELECT item_id
       , Group_concat(
           IF(condition IN (1, 2, 3) 
               AND ( price_date IS NULL OR price_date < Date_sub(Now(), INTERVAL 1 hour) ) 
               AND ( NOT ( price = bottomlimit AND pricebefore = bottomlimit AND pricebefore2 = bottomlimit ) 
                     OR price IS NULL 
                     OR pricebefore IS NULL 
                     OR pricebefore2 IS NULL 
                     OR Date(price_date) <> Curdate() 
                   ) 
              , storage_nr, NULL)
           SEPARATOR ','
         ) AS storage_nr 
       , [etc...]
FROM   items
WHERE  number > 0 AND bottomlimit IS NOT NULL 
GROUP  BY item_id 
HAVING storage_nr IS NOT NULL
ORDER  BY last_calc 
LIMIT  20
Uueerdo
  • 15,723
  • 1
  • 16
  • 21
  • Thanks, i try this, but the strange is - this table runs before with MyISAM much more faster than now with InnoDB - can this be normal? – Webbox Jul 27 '17 at 19:27
  • Did you shrink `key_buffer_size` and increase `innodb_buffer_pool_size`? – Rick James Jul 27 '17 at 23:46
0

You only hope to use indexed is to break down your complex query in a UNION of more simple and indexed query. First of all, you can use the FROM [subquery] syntax

SELECT item_id, 
       Group_concat(storage_nr SEPARATOR ',') AS storage_nr, 
       Group_concat(condition SEPARATOR ',') AS condition, 
       Group_concat(number SEPARATOR ',') AS number, 
       Group_concat(price SEPARATOR ',') AS price, 
       last_calc 
FROM   

SUBQUERY

AS items

GROUP  BY item_id 
ORDER  BY last_calc 
LIMIT  20

This could be your subquery:

SELECT *
FROM items
WHERE number > 0 
AND bottomlimit IS NOT NULL 
AND condition IN (1, 2, 3) 
AND price_date IS NULL 
AND ( NOT ( price = bottomlimit 
                   AND pricebefore = bottomlimit 
                   AND pricebefore2 = bottomlimit ) 
              OR price IS NULL 
              OR pricebefore IS NULL 
              OR pricebefore2 IS NULL 
              OR Date(price_date) <> Curdate() ) 

UNION ALL

SELECT *
FROM items
WHERE number > 0 
AND bottomlimit IS NOT NULL 
AND condition IN (1, 2, 3) 
AND price_date < Date_sub(Now(), INTERVAL 1 hour)
AND ( NOT ( price = bottomlimit 
                   AND pricebefore = bottomlimit 
                   AND pricebefore2 = bottomlimit ) 
              OR price IS NULL 
              OR pricebefore IS NULL 
              OR pricebefore2 IS NULL 
              OR Date(price_date) <> Curdate() ) 

Define the following index

- condition
- price_date
- bottomLimit

Please give me a feedback on the results. Thanks.

Stefano Losi
  • 719
  • 7
  • 18
0

Thanks for helping me!

The best solution for me was after testing everything to convert the table to MyISAM.

With this change i can speed the query up 3 to 5 times faster - from round about 12 seconds to less then 3 seconds.

Webbox
  • 25
  • 3
  • Had you increased `innodb_buffer_pool_size` then you wouldn't have to convert anything and would get better or same performance as with MyISAM. – Mjh Jul 28 '17 at 08:39