簡體   English   中英

MySQL 不同的引擎類型(InnoDB 和 Aria)是否會影響具有大量 LEFT JOIN 的查詢?

[英]Does MySQL different engine types (InnoDB and Aria) affect on query with large amount of LEFT JOIN?

我有一個帶有 12 LEFT JOIN的重型 MySQL 查詢,並注意到一些表有InnoDB引擎和一些Aria 我已經EXPLAIN了這個查詢的解釋,並在圖像上用相應的字母IA指出了引擎類型。

不同引擎的事實是否會影響查詢速度以及嚴重程度? 更改引擎類型是否有助於優化查詢執行?

我還能做些什么來優化這個查詢?

在此處輸入圖像描述

查詢(如果需要)

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, 0, 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, if (code_used.count > 0, code_used.count, 0) code_used_count, 
        if (user.is_pick_up, 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

UPD: CREATE TABLE

    CREATE TABLE `address` (
  `id` int(11) UNSIGNED NOT NULL,
  `location_id` int(11) UNSIGNED NOT NULL,
  `address` text NOT NULL,
  `unit` char(4) NOT NULL,
  `instructions` text NOT NULL,
  `regular` tinyint(1) NOT NULL DEFAULT '1',
  `topup` tinyint(1) NOT NULL DEFAULT '1',
  `date_from` date DEFAULT NULL,
  `date_to` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `address_pickup` (
  `id` tinyint(3) UNSIGNED NOT NULL,
  `address` text NOT NULL
) ENGINE=Aria DEFAULT CHARSET=utf8;

CREATE TABLE `code` (
  `id` smallint(6) UNSIGNED NOT NULL,
  `code` varchar(255) NOT NULL,
  `amount` decimal(7,2) NOT NULL,
  `value` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 - number; 1 - percent',
  `is_mswa` tinyint(4) DEFAULT '0',
  `is_permanent` tinyint(4) DEFAULT '0',
  `repeat` tinyint(4) DEFAULT '0',
  `apply_to` tinyint(4) DEFAULT '0' COMMENT '0 - both; 1 - box; 2 -  mp;',
  `times` int(11) NOT NULL DEFAULT '0',
  `date_created` datetime NOT NULL,
  `date_updated` datetime NOT NULL,
  `valid_from` date NOT NULL,
  `valid_until` date DEFAULT NULL,
  `author` varchar(255) NOT NULL,
  `checkout_text` text NOT NULL,
  `status` smallint(6) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `delivery_area` (
  `id` int(10) UNSIGNED NOT NULL,
  `location_id` int(11) NOT NULL,
  `fee` decimal(7,2) NOT NULL DEFAULT '0.00',
  `delivery_area_window_id` tinyint(4) UNSIGNED NOT NULL DEFAULT '1',
  `topup_available` tinyint(1) NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `delivery_area_window` (
  `id` tinyint(4) UNSIGNED NOT NULL,
  `day` tinyint(3) UNSIGNED NOT NULL,
  `day_name` varchar(255) NOT NULL,
  `day_name_full` varchar(255) NOT NULL,
  `window` varchar(255) NOT NULL DEFAULT '',
  `pickup` tinyint(4) NOT NULL DEFAULT '0'
) ENGINE=Aria DEFAULT CHARSET=utf8;


CREATE TABLE `gift` (
  `id` int(11) UNSIGNED NOT NULL,
  `user_id` int(11) UNSIGNED NOT NULL,
  `recipient_id` int(11) UNSIGNED NOT NULL,
  `type` tinyint(1) NOT NULL COMMENT '0 - card; 1 - box;',
  `message` text NOT NULL,
  `token` char(24) DEFAULT NULL,
  `order_id` int(11) UNSIGNED NOT NULL,
  `is_redeemed` tinyint(1) NOT NULL,
  `date_exp` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `location` (
  `id` int(10) UNSIGNED NOT NULL,
  `postcode` int(4) UNSIGNED NOT NULL,
  `suburb` varchar(45) NOT NULL,
  `dc` varchar(45) NOT NULL,
  `state_id` tinyint(3) UNSIGNED NOT NULL,
  `type_id` tinyint(4) UNSIGNED NOT NULL,
  `lat` double DEFAULT NULL,
  `lon` double DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=utf8;

CREATE TABLE `location_state` (
  `id` tinyint(4) UNSIGNED NOT NULL,
  `code` char(3) NOT NULL,
  `state` varchar(255) NOT NULL
) ENGINE=Aria DEFAULT CHARSET=utf8;

CREATE TABLE `order` (
  `id` int(11) UNSIGNED NOT NULL,
  `user_id` int(11) UNSIGNED NOT NULL,
  `shipping_address_id` int(11) UNSIGNED NOT NULL,
  `topup_address_id` int(10) UNSIGNED NOT NULL,
  `pickup_address_id` tinyint(3) UNSIGNED DEFAULT NULL,
  `preferences` int(11) UNSIGNED NOT NULL,
  `referral_discount` decimal(7,2) NOT NULL DEFAULT '0.00',
  `code_id` int(11) UNSIGNED NOT NULL,
  `code_discount` decimal(7,2) NOT NULL DEFAULT '0.00',
  `pickup_discount` decimal(7,2) NOT NULL DEFAULT '0.00',
  `admin_discount` decimal(7,2) NOT NULL DEFAULT '0.00',
  `level_discount` decimal(7,2) NOT NULL DEFAULT '0.00',
  `delivery_fee` decimal(7,2) NOT NULL DEFAULT '0.00',
  `topup_delivery_fee` decimal(7,2) NOT NULL,
  `ondemand_fee` decimal(7,2) NOT NULL DEFAULT '0.00',
  `amount` decimal(7,2) NOT NULL DEFAULT '0.00',
  `retry_payment` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '1-wait answer; 2-recharge with sms; 3-recharge without sms',
  `retry_payment_sms` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT '0 - processed; >0 - sms id',
  `retry_payment_email` int(10) UNSIGNED NOT NULL DEFAULT '0',
  `eway_errors` text NOT NULL,
  `date_created` datetime NOT NULL,
  `date_updated` datetime NOT NULL,
  `delivery_date` date DEFAULT NULL,
  `status` smallint(6) UNSIGNED NOT NULL DEFAULT '10',
  `processing_status` smallint(6) UNSIGNED NOT NULL,
  `processing_status_edited` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
  `has_topup` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
  `is_topup_only` tinyint(1) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

CREATE TABLE `user` (
  `id` int(11) UNSIGNED NOT NULL,
  `first_name` varchar(255) NOT NULL,
  `last_name` varchar(255) NOT NULL,
  `birthday` date DEFAULT NULL,
  `auth_key` varchar(32) NOT NULL,
  `password_hash` varchar(255) NOT NULL,
  `password_reset_token` varchar(255) DEFAULT NULL,
  `email` varchar(255) NOT NULL,
  `phone` varchar(255) DEFAULT NULL,
  `custom_ref_code` varchar(255) DEFAULT NULL,
  `eway_id` bigint(20) UNSIGNED DEFAULT NULL COMMENT 'eWAY Customer Token ID',
  `active_campaign_id` int(11) UNSIGNED DEFAULT NULL COMMENT 'ActiveCampaign subscriber_id',
  `level_id` tinyint(4) UNSIGNED NOT NULL DEFAULT '1',
  `address_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `delivery_area_id` int(10) UNSIGNED DEFAULT NULL,
  `alt_address_id` int(10) UNSIGNED DEFAULT NULL,
  `alt_delivery_area_id` int(10) UNSIGNED DEFAULT NULL,
  `code_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `period` tinyint(4) UNSIGNED NOT NULL DEFAULT '1' COMMENT '1 - Once a Week; 2 - Fortnightly',
  `preferences` int(11) UNSIGNED NOT NULL DEFAULT '0',
  `is_pick_up` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
  `pickup_address_id` tinyint(3) UNSIGNED DEFAULT NULL,
  `is_active` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0 - Inactive; 1 - Active; -1 - Blocked',
  `status` smallint(6) NOT NULL DEFAULT '10',
  `type` tinyint(4) UNSIGNED NOT NULL COMMENT '0 - Set And Forget; 1 - On Demand; 2 - Trial; 3 - Potential;',
  `first_delivery_date` date DEFAULT NULL,
  `last_delivery_date` date DEFAULT NULL,
  `change_delivery_date` date DEFAULT NULL,
  `nf_pantry_list` tinyint(1) NOT NULL DEFAULT '1',
  `nf_next_weeks_menu` tinyint(1) NOT NULL DEFAULT '1',
  `nf_paused_reminder` tinyint(1) NOT NULL DEFAULT '1',
  `nf_expected_delivery_time` tinyint(1) NOT NULL DEFAULT '1',
  `nf_delivery` tinyint(1) NOT NULL DEFAULT '1',
  `nf_welcome` tinyint(1) NOT NULL DEFAULT '1',
  `date_created` datetime NOT NULL,
  `date_updated` datetime NOT NULL,
  `consecutive_orders` smallint(5) UNSIGNED DEFAULT NULL,
  `orders_count` smallint(5) UNSIGNED NOT NULL DEFAULT '0',
  `rest_referral_discount` decimal(7,2) UNSIGNED NOT NULL,
  `rest_code_discount` decimal(7,2) UNSIGNED NOT NULL,
  `rest_code_box_discount` decimal(7,2) UNSIGNED NOT NULL,
  `rest_code_mp_discount` decimal(7,2) UNSIGNED NOT NULL,
  `rest_code_tup_discount` decimal(7,2) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `user_level` (
  `id` int(11) NOT NULL,
  `level` varchar(255) NOT NULL,
  `icon` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `from` int(11) NOT NULL DEFAULT '0',
  `to` int(11) NOT NULL DEFAULT '0',
  `discount` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

和索引

    --
-- Indexes table `address`
--
ALTER TABLE `address`
  ADD PRIMARY KEY (`id`),
  ADD KEY `location_id` (`location_id`),
  ADD KEY `regular` (`regular`),
  ADD KEY `topup` (`topup`),
  ADD KEY `date_to` (`date_to`),
  ADD KEY `date_from` (`date_from`);

--
-- Indexes table `address_pickup`
--
ALTER TABLE `address_pickup`
  ADD PRIMARY KEY (`id`);

--
-- Indexes table `code`
--
ALTER TABLE `code`
  ADD PRIMARY KEY (`id`),
  ADD KEY `status` (`status`),
  ADD KEY `valid_from` (`valid_from`),
  ADD KEY `valid_until` (`valid_until`),
  ADD KEY `date_created` (`date_created`),
  ADD KEY `code` (`code`) USING BTREE,
  ADD KEY `is_mswa` (`is_mswa`);

--
-- Indexes table `delivery_area`
--
ALTER TABLE `delivery_area`
  ADD PRIMARY KEY (`id`),
  ADD KEY `day` (`delivery_area_window_id`),
  ADD KEY `location_id` (`location_id`) USING BTREE,
  ADD KEY `friday_topup_available` (`topup_available`);

--
-- Indexes table `delivery_area_window`
--
ALTER TABLE `delivery_area_window`
  ADD PRIMARY KEY (`id`),
  ADD KEY `day` (`day`),
  ADD KEY `pickup_only` (`pickup`);

--
-- Indexes table `gift`
--
ALTER TABLE `gift`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `token` (`token`),
  ADD KEY `user_id` (`user_id`),
  ADD KEY `recipient_id` (`recipient_id`),
  ADD KEY `order_id` (`order_id`),
  ADD KEY `is_redeemed` (`is_redeemed`);

--
-- Indexes table `location`
--
ALTER TABLE `location`
  ADD PRIMARY KEY (`id`),
  ADD KEY `idx_lon` (`lon`),
  ADD KEY `idx_lat` (`lat`),
  ADD KEY `type_id` (`type_id`),
  ADD KEY `state_id` (`state_id`),
  ADD KEY `postcode` (`postcode`),
  ADD KEY `suburb_2` (`suburb`),
  ADD KEY `postcode_suburb` (`postcode`,`suburb`) USING BTREE;
ALTER TABLE `location` ADD FULLTEXT KEY `suburb` (`suburb`);

--
-- Indexes table `location_state`
--
ALTER TABLE `location_state`
  ADD PRIMARY KEY (`id`);

--
-- Indexes table `order`
--
ALTER TABLE `order`
  ADD PRIMARY KEY (`id`),
  ADD KEY `client_id` (`user_id`),
  ADD KEY `status` (`status`),
  ADD KEY `shipping_address_id` (`shipping_address_id`),
  ADD KEY `preferences` (`preferences`),
  ADD KEY `processing_status` (`processing_status`),
  ADD KEY `date_created` (`date_created`),
  ADD KEY `delivery_date` (`delivery_date`),
  ADD KEY `pickup_address_id` (`pickup_address_id`),
  ADD KEY `processing_status_edited` (`processing_status_edited`),
  ADD KEY `retry_payment_sms` (`retry_payment_sms`),
  ADD KEY `retry_payment` (`retry_payment`),
  ADD KEY `retry_payment_email` (`retry_payment_email`),
  ADD KEY `has_topup` (`has_topup`),
  ADD KEY `is_topup_only` (`is_topup_only`),
  ADD KEY `friday_address_id` (`topup_address_id`),
  ADD KEY `code_id` (`code_id`),
  ADD KEY `user_id` (`user_id`);

--
-- Indexes table `user`
--
ALTER TABLE `user`
  ADD PRIMARY KEY (`id`),
  ADD UNIQUE KEY `password_reset_token` (`password_reset_token`),
  ADD KEY `level_id` (`level_id`),
  ADD KEY `eway_id` (`eway_id`),
  ADD KEY `password_hash` (`password_hash`),
  ADD KEY `auth_key` (`auth_key`),
  ADD KEY `email` (`email`),
  ADD KEY `period` (`period`),
  ADD KEY `preferences` (`preferences`),
  ADD KEY `is_pick_up` (`is_pick_up`),
  ADD KEY `is_active` (`is_active`),
  ADD KEY `date_created` (`date_created`),
  ADD KEY `phone` (`phone`) USING BTREE,
  ADD KEY `active_campaign_id` (`active_campaign_id`),
  ADD KEY `custom_ref_code` (`custom_ref_code`),
  ADD KEY `consecutive_orders` (`consecutive_orders`),
  ADD KEY `pickup_address_id` (`pickup_address_id`),
  ADD KEY `rest_referral_discount` (`rest_referral_discount`),
  ADD KEY `rest_code_discount` (`rest_code_discount`),
  ADD KEY `rest_code_box_discount` (`rest_code_box_discount`),
  ADD KEY `rest_code_mp_discount` (`rest_code_mp_discount`),
  ADD KEY `delivery_area_id` (`delivery_area_id`),
  ADD KEY `rest_code_tup_discount` (`rest_code_tup_discount`),
  ADD KEY `orders_count` (`orders_count`),
  ADD KEY `alt_delivery_address_id` (`alt_address_id`),
  ADD KEY `alt_delivery_area_id` (`alt_delivery_area_id`),
  ADD KEY `address_id` (`address_id`),
  ADD KEY `code_id` (`code_id`),
  ADD KEY `status` (`status`),
  ADD KEY `type` (`type`),
  ADD KEY `last_name` (`last_name`);

--
-- Indexes table `user_level`
--
ALTER TABLE `user_level`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT
--
ALTER TABLE `address`
  MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `address_pickup`
  MODIFY `id` tinyint(3) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `code`
  MODIFY `id` smallint(6) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `delivery_area`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `delivery_area_window`
  MODIFY `id` tinyint(4) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `gift`
  MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `location`
  MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `location_state`
  MODIFY `id` tinyint(4) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `order`
  MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `user`
  MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `user_level`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;

對於表order

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

(我不知道哪個會更好;優化器可以決定。)

當“右”表不是可選的時,不要使用LEFT JOIN 這使得人類(和優化器)確定意圖變得乏味。

User需求

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

當您添加 INDEX(a,b) 時,DROP INDEX(a) 幾乎總是有益的。 我提出這個是因為你可能有一些單列索引。

如果您需要進一步的幫助,請提供SHOW CREATE TABLE 我懷疑這個查詢可以從里到外翻到很大的好處。 這涉及首先找到 15 個 id; 然后在那之后做所有的JOINs

這可能是第一個“派生”表,因為它只生成15 行,而不是解釋中估計的 9976:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM