[英]MySQL Left outer join query too slow
我有 3 张桌子:
订单(5429850 行),order_lines(PK id,FK order_id,18530647 行),order_line_allocations(PK id,FK order_line_id,112594 行)
order_lines
和order_line_allocations
存储帐户相关信息。 对于单账户情况,我们将账户数据存储在 order_lines 表中,对于多账户用例,我们将数据存储在分配表中。
我正在尝试编写一个查询来获取满足用户帐户限制的订单。
SELECT `orders`.`id` FROM `orders`
LEFT JOIN `order_lines` ON `order_lines`.`order_id` = `orders`.`id`
LEFT JOIN order_line_allocations ON order_line_allocations.order_line_id = order_lines.id
LEFT JOIN (select sec_accounts.id from accounts sec_accounts
WHERE (sec_accounts.account_type_id = 344 AND ((`sec_accounts`.`segment_1` = 'MS')))
) as non_alloc_accounts ON non_alloc_accounts.id = order_lines.account_id AND order_lines.allocation_count = 0
LEFT JOIN (select sec_accounts.id from accounts sec_accounts
WHERE (sec_accounts.account_type_id = 344 AND ((`sec_accounts`.`segment_1` = 'MS')))
) as alloc_accounts ON alloc_accounts.id = order_line_allocations.account_id
WHERE (`orders`.line_count = 0 OR
`orders`.account_type_id IS NULL OR
`orders`.account_type_id IN (NULL) OR
(non_alloc_accounts.id is not null) OR
(alloc_accounts.id is not null)
) ORDER BY `orders`.`id` ASC LIMIT 90 \G;
此查询需要 7 秒才能完成,太长了
但是,对于其他用户:
SELECT `orders`.`id` FROM `orders`
LEFT JOIN `order_lines` ON `order_lines`.`order_id` = `orders`.`id`
LEFT JOIN order_line_allocations ON order_line_allocations.order_line_id = order_lines.id
LEFT JOIN (select sec_accounts.id from accounts sec_accounts
WHERE (sec_accounts.account_type_id = 8 AND ((`sec_accounts`.`segment_1` = '2D')))
) as non_alloc_accounts ON non_alloc_accounts.id = order_lines.account_id AND order_lines.allocation_count = 0
LEFT JOIN (select sec_accounts.id from accounts sec_accounts
WHERE (sec_accounts.account_type_id = 8 AND ((`sec_accounts`.`segment_1` = '2D')))
) as alloc_accounts ON alloc_accounts.id = order_line_allocations.account_id
WHERE (`orders`.line_count = 0 OR
`orders`.account_type_id IS NULL OR
`orders`.account_type_id IN (NULL) OR
(non_alloc_accounts.id is not null) OR
(alloc_accounts.id is not null)
) ORDER BY `orders`.`id` ASC LIMIT 90 \G;
^ 这只需 0.03 秒。 请注意,不同之处在于 LEFT JOINS 的 where 子句。 特别是“=8”与“=344”在两个地方。
匹配 8 和 '2D' 的帐户数量是 175667,对于 344 和 'MS' 它只是 5648 。
我在所有表上都有所需的索引
表索引:
订单
PRIMARY KEY (`id`),
UNIQUE KEY `index_orders_on_po_number` (`po_number`),
KEY `index_orders_on_account_type_id` (`account_type_id`),
KEY `index_orders_on_created_by` (`created_by_id`),
KEY `index_orders_on_last_exported_at` (`last_exported_at`),
KEY `index_orders_on_status` (`status`),
KEY `index_orders_on_updated_at` (`updated_at`),
KEY `index_orders_on_updated_by` (`updated_by_id`),
KEY `index_orders_on_created_at_and_status` (`created_at`,`status`),
KEY `index_status_supplier_id` (`status`,`supplier_id`),
KEY `index_orders_on_line_count` (`line_count`)
order_lines
PRIMARY KEY (`id`),
UNIQUE KEY `index_order_lines_on_bulk_price_id` (`bulk_price_id`),
KEY `index_order_lines_on_account_type_id` (`account_type_id`),
KEY `index_order_lines_on_created_at` (`created_at`),
KEY `index_order_lines_on_created_by` (`created_by_id`),
KEY `index_order_lines_on_order_id` (`order_id`),
KEY `index_order_lines_on_status` (`status`),
KEY `index_order_lines_on_updated_at` (`updated_at`),
KEY `index_order_lines_on_updated_by` (`updated_by_id`),
KEY `index_order_lines_on_order_id_and_position` (`order_id`,`position`),
KEY `index_order_lines_on_order_id_and_line_num` (`order_id`,`line_num`),
KEY `index_ol_on_header_id_reporting_total_savings_pct_created_at` (`order_id`,`reporting_total`,`savings_pct`,`created_at`),
KEY `index_ol_on_order_id_supplier_id_reporting_total` (`order_id`,`supplier_id`,`reporting_total`),
KEY `index_ol_on_order_id_commodity_id_reporting_total_ela_id` (`order_id`,`commodity_id`,`reporting_total`,`extra_line_attribute_id`),
KEY `index_order_lines_on_allocation_count_and_account_id` (`allocation_count`,`account_id`),
KEY `index_order_lines_on_account_id` (`account_id`),
KEY `index_order_lines_on_allocation_count` (`allocation_count`),
KEY `index_ol_on_acc_id_alloc_count_order_id` (`account_id`,`allocation_count`,`order_id`),
KEY `index_ol_on_order_id_account_id_alloc_count` (`order_id`,`account_id`,`allocation_count`)
order_line_allocations
PRIMARY KEY (`id`),
KEY `index_order_line_allocations_on_account_id` (`account_id`),
KEY `index_order_line_allocations_on_account_type_id` (`account_type_id`),
KEY `index_order_line_allocations_on_order_id` (`order_id`),
KEY `index_order_line_allocations_on_order_line_id` (`order_line_id`)
帐户
PRIMARY KEY (`id`),
KEY `index_accounts_on_account_type_id_and_active` (`account_type_id`,`active`),
KEY `index_accounts_on_segment_1` (`segment_1`),
KEY `index_accounts_on_segment_10` (`segment_10`),
KEY `index_accounts_on_segment_11` (`segment_11`),
KEY `index_accounts_on_segment_12` (`segment_12`),
KEY `index_accounts_on_segment_13` (`segment_13`),
KEY `index_accounts_on_segment_14` (`segment_14`),
KEY `index_accounts_on_segment_15` (`segment_15`),
KEY `index_accounts_on_segment_16` (`segment_16`),
KEY `index_accounts_on_segment_17` (`segment_17`),
KEY `index_accounts_on_segment_18` (`segment_18`),
KEY `index_accounts_on_segment_19` (`segment_19`),
KEY `index_accounts_on_segment_2` (`segment_2`),
KEY `index_accounts_on_segment_20` (`segment_20`),
KEY `index_accounts_on_segment_3` (`segment_3`),
KEY `index_accounts_on_segment_4` (`segment_4`),
KEY `index_accounts_on_segment_5` (`segment_5`),
KEY `index_accounts_on_segment_6` (`segment_6`),
KEY `index_accounts_on_segment_7` (`segment_7`),
KEY `index_accounts_on_segment_8` (`segment_8`),
KEY `index_accounts_on_segment_9` (`segment_9`),
KEY `index_accounts_on_account_type_id` (`account_type_id`)
慢查询的解释计划
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: orders
partitions: NULL
type: index
possible_keys: index_orders_on_account_type_id,index_orders_on_line_count
key: PRIMARY
key_len: 4
ref: NULL
rows: 10
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: order_lines
partitions: NULL
type: ref
possible_keys: index_order_lines_on_order_id,index_order_lines_on_order_id_and_position,index_order_lines_on_order_id_and_line_num,index_ol_on_header_id_reporting_total_savings_pct_created_at,index_ol_on_order_id_supplier_id_reporting_total,index_ol_on_order_id_commodity_id_reporting_total_ela_id,index_ol_on_order_id_account_id_alloc_count
key: index_ol_on_order_id_commodity_id_reporting_total_ela_id
key_len: 4
ref: perf_amazon_qas1481_utf8mb4.orders.id
rows: 2
filtered: 100.00
Extra: NULL
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: order_line_allocations
partitions: NULL
type: ref
possible_keys: index_order_line_allocations_on_order_line_id
key: index_order_line_allocations_on_order_line_id
key_len: 5
ref: perf_amazon_qas1481_utf8mb4.order_lines.id
rows: 3
filtered: 100.00
Extra: NULL
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: sec_accounts
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,index_accounts_on_account_type_id_and_active,index_accounts_on_segment_1,index_accounts_on_account_type_id
key: PRIMARY
key_len: 4
ref: perf_amazon_qas1481_utf8mb4.order_lines.account_id
rows: 1
filtered: 100.00
Extra: Using where
*************************** 5. row ***************************
id: 1
select_type: SIMPLE
table: sec_accounts
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,index_accounts_on_account_type_id_and_active,index_accounts_on_segment_1,index_accounts_on_account_type_id
key: PRIMARY
key_len: 4
ref: perf_amazon_qas1481_utf8mb4.order_line_allocations.account_id
rows: 1
filtered: 100.00
Extra: Using where
EXPLAIN PLAN 快速查询:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: orders
partitions: NULL
type: index
possible_keys: index_orders_on_account_type_id,index_orders_on_line_count
key: PRIMARY
key_len: 4
ref: NULL
rows: 10
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: order_lines
partitions: NULL
type: ref
possible_keys: index_order_lines_on_order_id,index_order_lines_on_order_id_and_position,index_order_lines_on_order_id_and_line_num,index_ol_on_header_id_reporting_total_savings_pct_created_at,index_ol_on_order_id_supplier_id_reporting_total,index_ol_on_order_id_commodity_id_reporting_total_ela_id,index_ol_on_order_id_account_id_alloc_count
key: index_ol_on_order_id_commodity_id_reporting_total_ela_id
key_len: 4
ref: perf_amazon_qas1481_utf8mb4.orders.id
rows: 2
filtered: 100.00
Extra: NULL
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: order_line_allocations
partitions: NULL
type: ref
possible_keys: index_order_line_allocations_on_order_line_id
key: index_order_line_allocations_on_order_line_id
key_len: 5
ref: perf_amazon_qas1481_utf8mb4.order_lines.id
rows: 3
filtered: 100.00
Extra: NULL
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: sec_accounts
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,index_accounts_on_account_type_id_and_active,index_accounts_on_segment_1,index_accounts_on_account_type_id
key: PRIMARY
key_len: 4
ref: perf_amazon_qas1481_utf8mb4.order_lines.account_id
rows: 1
filtered: 100.00
Extra: Using where
*************************** 5. row ***************************
id: 1
select_type: SIMPLE
table: sec_accounts
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,index_accounts_on_account_type_id_and_active,index_accounts_on_segment_1,index_accounts_on_account_type_id
key: PRIMARY
key_len: 4
ref: perf_amazon_qas1481_utf8mb4.order_line_allocations.account_id
rows: 1
filtered: 100.00
Extra: Using where
如何加快查询速度?
这些复合索引可能会有所帮助:
order_lines: INDEX(order_id, account_id, allocation_count)
order_line_allocations: INDEX(order_line_id, account_id)
accounts: INDEX(account_type_id, segment_1)
添加复合索引时,删除具有相同前导列的索引。 也就是说,当您同时拥有INDEX(a)
和INDEX(a,b)
时,扔掉前者。
可以将两个LEFT JOINs
合并到accounts
中吗?
如需进一步讨论,请为每个表提供SHOW CREATE TABLE
。 并EXPLAIN
8 和 344。
OR
使得使用INDEX
进行优化变得不切实际。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.