[英]MySQL query extreme slow filtering on CASE WHEN formula
使用MySQL 5.6時,使用CASE WHEN THEN ELSE END
語法的條件對計算公式進行過濾時,會遇到很大的性能問題。
該SQL公式由Hibernate映射。 數據庫中約有6000行。
表foo
在列product
和barcode
上具有索引
1.慢2-16秒
select
count(*)
from
foo AS f
where
(
CASE WHEN f.product IS NOT NULL THEN 1
ELSE (
CASE WHEN f.barcode IS NULL THEN 0
ELSE (
SELECT EXISTS(
SELECT 1
FROM product AS p
WHERE p.barcode = f.barcode
LIMIT 1
)
) END
) END
) = 0
EXPLAIN
結果:
+----+--------------------+-------+------+-------------------------------+-----+---------+-----+-------+---------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+------+-------------------------------+-----+---------+-----+-------+---------------------------------------------------+
| 1 | PRIMARY | f | ALL | | | | | 700 | Using where |
| 3 | DEPENDENT SUBQUERY | p | ALL | UQ_product,IX_product_barcode | | | | 3134 | Range checked for each record (index map: 0x2008) |
+----+--------------------+-------+------+-------------------------------+-----+---------+-----+-------+---------------------------------------------------+
2.快速〜0.4 s
select
*
from
foo AS f
where
(CASE ... END) = 0
EXPLAIN
結果與計數查詢相同。
首先,您可能應該嘗試查看EXPLAIN
的輸出以獲取更多信息。
但是,無論哪種方式,讓我們嘗試稍微清理一下查詢,看看是否無法利用一些索引。 最大的氣味是CASE xxx = 0
; 我想知道查詢解析器是否在制定有效計划時遇到麻煩,並且正在計算每行的該值並將結果與0進行比較。
因此,我們將其重寫為:
where f.product is null
and (
f.barcode is null
or exists (select 1 from product p where p.barcode = f.barcode)
)
如果這不能解決問題,請嘗試使用ANALYZE TABLE
更新索引統計信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.