在mariadb中,相同数据库上的查询运行时间为0.4秒,在mysql 5.6、5.7和8中为83秒

在mariadb中,相同数据库上的查询运行时间为0.4秒,在mysql 5.6、5.7和8中为83秒,mysql,mariadb,Mysql,Mariadb,我有一个在mysql上运行非常慢(83秒)但在mariadb上运行非常快的查询(.4秒) 我验证了数据数据库具有相同的索引和数据。Maria Db服务器的cpu(1VCPU)、内存(2gb)更少 Mysql服务器有8-32GB的ram和全四核处理器(尝试了5.6、5.7和8.0,结果类似) phppos_库存表约有170000行,phppos_物料表约有3000行 下面是查询和表,并进行了说明 SELECT /*+ SEMIJOIN(@subq MATERIALIZATION) */ SQL_C

我有一个在mysql上运行非常慢(83秒)但在mariadb上运行非常快的查询(.4秒)

我验证了数据数据库具有相同的索引和数据。Maria Db服务器的cpu(1VCPU)、内存(2gb)更少

Mysql服务器有8-32GB的ram和全四核处理器(尝试了5.6、5.7和8.0,结果类似)

phppos_库存表约有170000行,phppos_物料表约有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 
解释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字符限制)

创建表:

MYSQL(开发盒)

玛丽亚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)

MariaDB和MySQL的优化器在5.6版本开始出现显著差异。某些查询在其中一个查询中运行的速度比另一个查询快

我想我看到了一种加快查询速度的方法,也许在两个版本上都是如此

  • 当与
    连接
    相同时,不要使用
    左连接
    ,这似乎至少适用于
    phppos_项目
    ,该项目位于覆盖
    位置


  • 请提供
    显示创建表
    ;同时,我将猜测您有/没有哪些索引,以及每个表都有
    主键(id)

  • 在适当的地方使用复合索引。(详见下文。)

  • 在将连接到其余表之前获取20行:

    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)
    

MariaDB和MySQL的优化器在5.6版本时开始出现显著差异。某些查询在其中一个查询中运行的速度比另一个查询快

我想我看到了一种加快查询速度的方法,也许在两个版本上都是如此

  • 当与
    连接
    相同时,不要使用
    左连接
    ,这似乎至少适用于
    phppos_项目
    ,该项目位于覆盖
    位置


  • 请提供
    显示创建表
    ;同时,我将猜测您有/没有哪些索引,以及每个表都有
    主键(id)

  • 在适当的地方使用复合索引。(详见下文。)

  • 在将连接到其余表之前获取20行:

    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)
    

除了由于外部联接被丢弃而导致查询误导之外,主要区别在于MariabDB中的第二个引擎操作是使用
phppos\u inventory\u自定义
索引进行索引范围扫描(
ref
)。MySQL也选择了索引范围扫描,但超过了
phppos\u inventory\u ibfk\u 1

然而,如果没有这两个索引的定义,很难评估引擎为什么选择了不同的路径


请在您的问题中添加这些索引的定义,以及它们的选择性(所选估计行的百分比/表总行数)以详细说明。

除了由于外部联接被丢弃而导致查询产生误导之外,主要区别在于MariabDB中的第二个引擎操作是索引范围扫描(
ref
)使用
phppos_inventory_custom
索引。MySQL也选择了索引范围扫描,但选择了
phppos_inventory_ibfk_1

然而,如果没有这两个索引的定义,很难评估引擎为什么选择了不同的路径

请在您的问题中添加这些索引的定义,以及它们的选择性(所选估计行的百分比/表总行数),以详细说明。

移动

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
内部连接(
选择inv1.trans\u items、inv1.item\u variation\u id、inv1.location\u id、MAX(inv1.trans\u id)作为trans\u id
来自phppos_库存inv1
其中inv1.trans_日期<'2019-12-31 23:59:59'
按inv1.trans\u项目、inv1.item\u变体\u id、inv1.location\u id分组
按inv1.trans\u项目、inv1.item\u变体\u id、inv1.location\u id订购
)inv1.trans\U id上的inv1=inv.trans\U id
和inv1.trans\u项目=inv.trans\u项目
和(inv1.item_variation_id=phppos_item_variations.id或phppos_item_variations.id为空)
和inv1.location\u id=inv.location\u id
执行时间从80+s减少到~移动

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
内部连接(
选择inv1.trans\u items、inv1.item\u variation\u id、inv1.location\u id、MAX(inv1.trans\u id)作为trans\u id
来自phppos_库存inv1
其中inv1.trans_日期<'2019-12-31 23:59:59'
按inv1.trans\u项目、inv1.item\u变体\u id、inv1.location\u id分组
按inv1.trans\u项目、inv1.item\u变体\u id、inv1.location\u id订购
)inv1.trans\U id上的inv1=inv.trans\U id
和inv1.trans\u项目=inv.trans\u项目
和(inv1.item_variation_id=phppos_item_variations.id或phppos_item_variations.id为空)
和inv1.location\u id=inv.location\u id

执行时间从80+s减少到~您的查询是错误的。筛选谓词
和phppos_items.system_item=0
会破坏外部联接,有效地将其转换为内部联接。接下来的两个谓词也是如此。首先修复此问题,然后我们可以对其进行优化。
SHOW CREATE TABLE
比o与
description
(也可以是较少的文本)相比,阅读索引顺序。选择有趣的
delete
作为索引,而不是
deleted\u system\u item
,因为我假设命名是顺序。听起来你有一个“使用MariaDB”作为解决方案:-)顺便问一下,哪个MariaDB版本?您有一个没有
订单的限额
?有人告诉我,作为默认顺序的组已被弃用。Maria db 10.2.31您的发布结果是否可以显示全局状态,如“%thread%”;从MySQL和MariaDB服务器?连接lft=rgt每侧的数据类型和(长度)在t的描述中是否相同