MySQL 不同的引擎类型InnoDB 和 Aria是否会影响具有大量 LEFT JOIN 的查询?

问题描述

我有一个包含 12 1 的繁重 MysqL 查询,并注意到一些表具有 category3 引擎和一些 LEFT JOIN。 我已附上此查询InnoDB,并用相应的字母 AriaEXPLAIN 将引擎类型指向图像。

不同引擎的事实对查询速度有影响吗?严重程度如何?更改引擎类型是否有助于优化查询执行?

我还能做些什么来优化这个查询

enter image description here

查询(如果需要)

I

更新:A

SELECT user.id,user.first_name,user.last_name,user.birthday,user.email,user.phone,user.address_id,user.alt_address_id,user.type,user.level_id,user_level.level,user.consecutive_orders,user.orders_count,user.code_id,user.period,user.preferences,user.is_pick_up,user.pickup_address_id,user.is_active,user.first_delivery_date,user.change_delivery_date,user.eway_id,user.date_created,user.rest_referral_discount as `rest_referral_discount`,user.rest_code_discount as `rest_code_discount`,user.rest_code_Box_discount as `rest_code_Box_discount`,user.rest_code_mp_discount as `rest_code_mp_discount`,user.rest_code_tup_discount as `rest_code_tup_discount`,user.nf_pantry_list,user.nf_next_weeks_menu,user.nf_paused_reminder,user.nf_welcome,user.nf_expected_delivery_time,user.nf_delivery,address_pickup.address as `pickup_address`,address.address,address.unit,address.instructions,location.id location_id,location.postcode,location.suburb,location_state.code state_code,delivery_area.delivery_area_window_id delivery_area_window_id,delivery_area_by_location.fee delivery_fee_value,delivery_area_window.day delivery_day,delivery_area_window.day_name_full delivery_day_name_full,delivery_area_window.window delivery_window,user.delivery_area_id,user.alt_delivery_area_id,if (user.is_pick_up,delivery_area.fee) delivery_fee,if (user.type = 1 || user.type = 2,5,0) ondemand_fee,code.code code_name,code.amount code_amount,code.value code_value,code.is_permanent is_code_permanent,code.repeat code_repeat,code.times code_times,code.apply_to code_apply_to,code.valid_from code_valid_from,code.valid_until code_valid_until,if (code_used.count > 0,1,0) is_code_used,code_used.count,0) code_used_count,IFNULL(delivery_area_by_location.topup_available,0),IFNULL(delivery_area.topup_available,0)) topup_available,(SELECT `order`.`id` FROM `order` LEFT JOIN `gift` ON gift.order_id = order.id 
        WHERE (`order`.`delivery_date` BETWEEN '2021-02-07' and '2021-02-13') and (user.id = order.user_id) and (`gift`.`id` IS NULL) 
        and (`order`.`status` = 10) ORDER BY `order`.`date_created` DESC LIMIT 1) as `order_id`,(SELECT `order`.`delivery_date` FROM `order` 
        LEFT JOIN `gift` 
            ON gift.order_id = order.id 
        WHERE (user.id = order.user_id) and (`gift`.`id` IS NULL) and (`order`.`status` = 10) ORDER BY `order`.`date_created` DESC LIMIT 1) as `last_order_delivery_date` 
        
        FROM `user` 
        
        LEFT JOIN `address` 
            ON user.address_id = address.id 
        LEFT JOIN `address_pickup` 
            ON user.pickup_address_id = address_pickup.id 
        LEFT JOIN `delivery_area` 
            ON user.delivery_area_id = delivery_area.id 
        LEFT JOIN `delivery_area_window` 
            ON delivery_area_window.id = delivery_area.delivery_area_window_id 
        LEFT JOIN `user_level` 
            ON user.level_id = user_level.id 
        LEFT JOIN `location` 
            ON address.location_id = location.id 
        LEFT JOIN `location_state` 
            ON location.state_id = location_state.id 
        LEFT JOIN `delivery_area` `delivery_area_by_location` ON delivery_area_by_location.location_id = location.id 
        LEFT JOIN (SELECT count(*) count,`user_id`,`code_id` FROM `order` WHERE (code_id > 0) and (`order`.`status` = 10) GROUP BY `user_id`,`code_id`) `code_used` 
            ON ((user.id = code_used.user_id) and (code_used.code_id = user.code_id)) 
        LEFT JOIN `code` 
            ON user.code_id = code.id WHERE (`user`.`type` = 0) and (`user`.`status` = 10) 
            
        GROUP BY `user`.`id` ORDER BY `last_name` LIMIT 15

和索引

CREATE TABLE

解决方法

对于表 order

INDEX(status,code_id,order_id)
INDEX(status,order_id,code_id)

(我不知道哪个更好;优化器可以决定。)

当“右”表不是可选的时,不要使用 LEFT JOIN。人类(和优化器)弄清意图变得乏味。

User 需要

 INDEX(type,status,code,id,last_name)

当您添加 INDEX(a,b) 时,DROP INDEX(a) 几乎总是有益的。我提出这一点是因为您可能有一些单列索引。

如果您需要进一步的帮助,请提供SHOW CREATE TABLE。我怀疑该查询可以由内而外转换以获得很大的好处。这涉及到 first 找到 15 个 id;然后在那之后做所有的JOINs

这可能是第一个“派生”表,因为它只生成 15 行,而不是解释中估计的 9976:

FROM ( SELECT  id,`code`,last_name
        FROM user
        WHERE  `type` = 0
          AND  `status` = 10
        GROUP BY  `id`
        ORDER BY  `last_name`
        LIMIT  15
     ) AS u
JOIN ...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...