Запрос к той же базе данных выполняется за 0,4 секунды в mariadb и 83 секунды в mysql 5,6,5,7 и 8 - PullRequest
0 голосов
/ 22 апреля 2020

У меня следующий запрос, который выполняется очень медленно на mysql (83 секунды), но очень быстро на mariadb (.4 секунды).

Я проверил, что база данных имеет те же индексы и данные. Сервер Maria Db имеет меньшее количество процессоров (1VCPU), память (2 ГБ)

Mysql Серверы имеют 8 - 32 ГБ ОЗУ и четырехъядерные процессоры (пробовал 5.6,5.7 и 8.0 с аналогичными результатами).

В таблице phppos_inventory ~ 170000 строк, а в таблице phppos_items ~ 3000 строк

Вот запрос, таблицы и пояснения

SELECT /*+ SEMIJOIN(@subq MATERIALIZATION) */ SQL_CALC_FOUND_ROWS 
1                                            AS _h, 
`phppos_location_items`.`location_id`        AS `location_id`, 
`phppos_items`.`item_id`, 
`phppos_items`.`name`, 
`phppos_categories`.`id`                     AS `category_id`, 
`phppos_categories`.`name`                   AS `category`, 
`location`, 
`company_name`, 
`phppos_items`.`item_number`, 
`size`, 
`product_id`, 
Coalesce(phppos_location_item_variations.cost_price, 
phppos_item_variations.cost_price, phppos_location_items.cost_price, 
phppos_items.cost_price, 0)                  AS cost_price, 
Coalesce(phppos_location_item_variations.unit_price, 
phppos_item_variations.unit_price, phppos_location_items.unit_price, 
phppos_items.unit_price, 0)                  AS unit_price, 
Sum(Coalesce(inv.trans_current_quantity, 0)) AS quantity, 
Coalesce(phppos_location_item_variations.reorder_level, 
phppos_item_variations.reorder_level, phppos_location_items.reorder_level, 
phppos_items.reorder_level)                  AS reorder_level, 
Coalesce(phppos_location_item_variations.replenish_level, 
phppos_item_variations.replenish_level, phppos_location_items.replenish_level, 
phppos_items.replenish_level)                AS replenish_level, 
description 
FROM   `phppos_inventory` `inv` 
       LEFT JOIN `phppos_items` 
              ON `phppos_items`.`item_id` = `inv`.`trans_items` 
       LEFT JOIN `phppos_location_items` 
              ON `phppos_location_items`.`item_id` = `phppos_items`.`item_id` 
                 AND `phppos_location_items`.`location_id` = `inv`.`location_id` 
       LEFT JOIN `phppos_item_variations` 
              ON `phppos_items`.`item_id` = `phppos_item_variations`.`item_id` 
                 AND `phppos_item_variations`.`id` = `inv`.`item_variation_id` 
                 AND `phppos_item_variations`.`deleted` = 0 
       LEFT JOIN `phppos_location_item_variations` 
              ON `phppos_location_item_variations`.`item_variation_id` = 
                           `phppos_item_variations`.`id` 
                 AND `phppos_location_item_variations`.`location_id` = 
                     `inv`.`location_id` 
       LEFT OUTER JOIN `phppos_suppliers` 
                    ON `phppos_items`.`supplier_id` = 
                       `phppos_suppliers`.`person_id` 
       LEFT OUTER JOIN `phppos_categories` 
                    ON `phppos_items`.`category_id` = `phppos_categories`.`id` 
WHERE  inv.trans_id = (SELECT Max(inv1.trans_id) 
                       FROM   phppos_inventory inv1 
                       WHERE  inv1.trans_items = inv.trans_items 
                              AND ( inv1.item_variation_id = 
                                    phppos_item_variations.id 
                                     OR phppos_item_variations.id IS NULL ) 
                              AND inv1.location_id = inv.location_id 
                              AND inv1.trans_date < '2019-12-31 23:59:59') 
       AND inv.location_id IN( 1 ) 
       AND `phppos_items`.`system_item` = 0 
       AND `phppos_items`.`deleted` = 0 
       AND `is_service` != 1 
GROUP  BY `phppos_items`.`item_id` 
LIMIT  20 

Объясните mysql (немного отличается от maria db, но я пытался использовать index, чтобы соответствовать плану выполнения, и все еще был медленным)

+------------------------------------------+-------+----------+------------------------------------+
| id | select_type        | table                           | partitions | type   | possible_keys                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | key                     | key_len | ref                                     | rows  | filtered | Extra                              |
+----+--------------------+---------------------------------+------------+--------+------------------------------+-------+----------+------------------------------------+
|  1 | PRIMARY            | phppos_items                    | NULL       | ref    | PRIMARY,item_number,product_id,phppos_items_ibfk_1,deleted,phppos_items_ibfk_3,phppos_items_ibfk_4,phppos_items_ibfk_5,description,size,reorder_level,cost_price,unit_price,promo_price,last_modified,name,phppos_items_ibfk_6,deleted_system_item,custom_field_1_value,custom_field_2_value,custom_field_3_value,custom_field_4_value,custom_field_5_value,custom_field_6_value,custom_field_7_value,custom_field_8_value,custom_field_9_value,custom_field_10_value,verify_age,phppos_items_ibfk_7,item_inactive_index,tags,full_search,name_search,item_number_search,product_id_search,description_search,size_search,custom_field_1_value_search,custom_field_2_value_search,custom_field_3_value_search,custom_field_4_value_search,custom_field_5_value_search,custom_field_6_value_search,custom_field_7_value_search,custom_field_8_value_search,custom_field_9_value_search,custom_field_10_value_search | deleted                 | 4       | const                                   | 21188 |     9.00 | Using index condition; Using where |
|  1 | PRIMARY            | inv                             | NULL       | ref    | phppos_inventory_ibfk_1,location_id,phppos_inventory_custom                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | phppos_inventory_custom | 8       | pos.phppos_items.item_id,const          |     3 |   100.00 | NULL                               |
|  1 | PRIMARY            | phppos_location_items           | NULL       | eq_ref | PRIMARY,phppos_location_items_ibfk_2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | PRIMARY                 | 8       | const,pos.phppos_items.item_id          |     1 |   100.00 | NULL                               |
|  1 | PRIMARY            | phppos_item_variations          | NULL       | eq_ref | PRIMARY,phppos_item_variations_ibfk_1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | PRIMARY                 | 4       | pos.inv.item_variation_id               |     1 |   100.00 | Using where                        |
|  1 | PRIMARY            | phppos_location_item_variations | NULL       | eq_ref | PRIMARY,phppos_item_attribute_location_values_ibfk_2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               | PRIMARY                 | 8       | pos.phppos_item_variations.id,const     |     1 |   100.00 | NULL                               |
|  1 | PRIMARY            | phppos_suppliers                | NULL       | ref    | person_id                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | person_id               | 4       | pos.phppos_items.supplier_id            |     1 |   100.00 | NULL                               |
|  1 | PRIMARY            | phppos_categories               | NULL       | eq_ref | PRIMARY                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | PRIMARY                 | 4       | pos.phppos_items.category_id            |     1 |   100.00 | NULL                               |
|  2 | DEPENDENT SUBQUERY | inv1                            | NULL       | ref    | phppos_inventory_ibfk_1,location_id,trans_date,phppos_inventory_ibfk_4,phppos_inventory_custom                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | phppos_inventory_custom | 8       | pos.inv.trans_items,pos.inv.location_id |     3 |    50.00 | Using where; Using index           |
+----+--------------------+---------------------------------+------------+--------+---------------------------------------------------------------------------------------------------------

Объяснить maria db:

+------+---------------------------------------------+-------+--------------------------+
| id   | select_type        | table                           | type   | possible_keys                                                                                  | key                     | key_len | ref                                                           | rows  | Extra                    |
+------+--------------------+---------------------------------+--------+------------------------------+
|    1 | PRIMARY            | phppos_items                    | ref    | PRIMARY,deleted,deleted_system_item                                                            | deleted                 | 4       | const                                                         | 23955 | Using where              |
|    1 | PRIMARY            | inv                             | ref    | phppos_inventory_ibfk_1,location_id,phppos_inventory_custom                                    | phppos_inventory_ibfk_1 | 4       | freelance_pos5.phppos_items.item_id                           |     2 | Using where              |
|    1 | PRIMARY            | phppos_location_items           | eq_ref | PRIMARY,phppos_location_items_ibfk_2                                                           | PRIMARY                 | 8       | const,freelance_pos5.phppos_items.item_id                     |     1 |                          |
|    1 | PRIMARY            | phppos_item_variations          | eq_ref | PRIMARY,phppos_item_variations_ibfk_1                                                          | PRIMARY                 | 4       | freelance_pos5.inv.item_variation_id                          |     1 | Using where              |
|    1 | PRIMARY            | phppos_location_item_variations | eq_ref | PRIMARY,phppos_item_attribute_location_values_ibfk_2                                           | PRIMARY                 | 8       | freelance_pos5.phppos_item_variations.id,const                |     1 | Using where              |
|    1 | PRIMARY            | phppos_suppliers                | ref    | person_id                                                                                      | person_id               | 4       | freelance_pos5.phppos_items.supplier_id                       |     1 | Using where              |
|    1 | PRIMARY            | phppos_categories               | eq_ref | PRIMARY                                                                                        | PRIMARY                 | 4       | freelance_pos5.phppos_items.category_id                       |     1 | Using where              |
|    2 | DEPENDENT SUBQUERY | inv1                            | ref    | phppos_inventory_ibfk_1,location_id,trans_date,phppos_inventory_ibfk_4,phppos_inventory_custom | phppos_inventory_custom | 8       | freelance_pos5.inv.trans_items,freelance_pos5.inv.location_id |     2 | Using where; Using index |
+------+--------------------+---------------------------------+--------+------------------------------------------------------------------------------------------------+-------------------------+---------+---------------------------------------------------------------+-------+--------------------------+

Описанные таблицы (достигнуто ограничение числа символов StackOverflow)

https://pastebin.com/nhngSHb8

Создание таблиц:

https://pastebin.com/aWMeriqt

MYSQL (DEV BOX)

mysql> SHOW GLOBAL STATUS LIKE '%thread%';
+------------------------------------------+-------+
| Variable_name                            | Value |
+------------------------------------------+-------+
| Delayed_insert_threads                   | 0     |
| Performance_schema_thread_classes_lost   | 0     |
| Performance_schema_thread_instances_lost | 0     |
| Slow_launch_threads                      | 0     |
| Threads_cached                           | 4     |
| Threads_connected                        | 1     |
| Threads_created                          | 5     |
| Threads_running                          | 1     |
+------------------------------------------+-------+
8 rows in set (0.06 sec)

MARIA DB

MariaDB [freelance_pos5]> SHOW GLOBAL STATUS LIKE '%thread%';
+------------------------------------------+-------+
| Variable_name                            | Value |
+------------------------------------------+-------+
| Delayed_insert_threads                   | 0     |
| Performance_schema_thread_classes_lost   | 0     |
| Performance_schema_thread_instances_lost | 0     |
| Slow_launch_threads                      | 0     |
| Threadpool_idle_threads                  | 0     |
| Threadpool_threads                       | 0     |
| Threads_cached                           | 3     |
| Threads_connected                        | 2     |
| Threads_created                          | 5     |
| Threads_running                          | 1     |
| wsrep_applier_thread_count               | 0     |
| wsrep_rollbacker_thread_count            | 0     |
| wsrep_thread_count                       | 0     |
+------------------------------------------+-------+
13 rows in set (0.00 sec)

Ответы [ 3 ]

1 голос
/ 29 апреля 2020

Перемещение

WHERE inv.trans_id = (SELECT Max(inv1.trans_id) 

во ВНУТРЕННЕЕ СОЕДИНЕНИЕ меняет правила игры.

INNER JOIN (
    SELECT inv1.trans_items, inv1.item_variation_id, inv1.location_id, MAX(inv1.trans_id) as trans_id
        FROM phppos_inventory inv1
        WHERE inv1.trans_date < '2019-12-31 23:59:59'
    GROUP BY inv1.trans_items, inv1.item_variation_id, inv1.location_id
    ORDER BY inv1.trans_items, inv1.item_variation_id, inv1.location_id
) inv1 on inv1.trans_id = inv.trans_id
    AND inv1.trans_items = inv.trans_items 
    AND (inv1.item_variation_id = phppos_item_variations.id OR phppos_item_variations.id IS NULL) 
    AND inv1.location_id = inv.location_id

Выполнение уменьшено с 80 + с до ~ <0,4 с при MySQL 8,0. </p>

1 голос
/ 25 апреля 2020
Оптимизаторы

MariaDB и MySQL начали значительно расходиться на 5,6. Некоторые запросы будут выполнять запросы быстрее в одном, чем в другом.

Мне кажется, я вижу способ ускорить запрос, возможно, в обеих версиях.

  • Не используйте LEFT JOIN, когда оно совпадает с JOIN, что, по-видимому, имеет место как минимум для phppos_items, в котором есть элементы в WHERE, которые переопределяют LEFT.

  • Пожалуйста, предоставьте SHOW CREATE TABLE; тем временем я буду догадываться, какие у вас индексы есть / нет, и что каждая таблица имеет PRIMARY KEY(id)

  • Используйте составные индексы, где это уместно. (Подробнее ниже.)

  • Получите 20 строк до JOINing для остальных таблиц:

    SELECT ...
        FROM ( SELECT inv.id, pi.id
                FROM  `phppos_inventory` AS inv `inv`
                JOIN  `phppos_items` AS pi
                     ON pi.`item_id` = `inv`.`trans_items`
                  AND  inv.location_id IN( 1 )
                  AND  pi.`system_item` = 0
                  AND  pi.`deleted` = 0
                  AND  `is_service` != 1   -- Which table is this in???
                GROUP BY  pi.`item_id`
                LIMIT  20 )
        LEFT JOIN .... (( all the other tables ))
        -- no GROUP BY or LIMIT needed (I think)
    
    phppos_items:  INDEX(item_id, deleted, system_item, is_service)
    phppos_items:  INDEX(deleted, system_item, is_service)
    phppos_inventory:  INDEX(trans_items, location_id, location_id, item_variation_id, trans_date, trans_id)
    phppos_inventory:  INDEX(location_id)
    
0 голосов
/ 25 апреля 2020

Помимо того факта, что запрос вводит в заблуждение, поскольку внешнее объединение отбрасывается, основное отличие состоит в том, что второй операцией двигателя в MariabDB является сканирование диапазона индекса (ref) с использованием phppos_inventory_custom индекс. MySQL также выбрал сканирование диапазона индекса , но более phppos_inventory_ibfk_1.

Однако без определения этих двух индексов трудно оценить, почему двигатели могли выбрать другой путь.

Пожалуйста, добавьте к своему вопросу определение этих индексов и укажите их селективность. (процент от оцененных выбранных строк / общее количество строк таблицы), чтобы уточнить подробнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...