[英]improve sql query with 2 EXISTS sub queries
我有這個查詢(mysql):
SELECT `budget_items`.*
FROM `budget_items`
WHERE (budget_category_id = 4
AND ((is_custom_for_family = 0)
OR (is_custom_for_family = 1
AND custom_item_family_id = 999))
AND ((EXISTS
(SELECT 1
FROM balance_histories
WHERE balance_histories.budget_item_id = budget_items.id
AND balance_histories.family_id = 999
AND payment_date >= '2021-02-01'
AND payment_date <= '2021-02-28' ))
OR (EXISTS
(SELECT 1
FROM budget_lines
WHERE family_id = 999
AND budget_id = 188311
AND budget_item_id = budget_items.id
AND amount > 0))))
它在應用程序啟動時運行多次。 需要超過 10 秒(全部)。
我有索引:
balance_histories 表:budget_item_id,family_id(也嘗試過 payment_date)
budget_lines 表:family_id、budget_id、budget_item_id
我怎樣才能提高速度? 查詢或可能是 mysql (8) 配置。
我會以與你所擁有的相反的方式開始這個查詢。 假設您可能擁有多年的數據,但您的 EXISTS 查詢正在更具體地查看日期范圍或特定預算線,從那里開始,它可能會小得多。 一旦您擁有 DISTINCT ID,然后 go 通過合格 ID 加上附加條件回到預算項目。
為了幫助優化查詢,我會在
table index
balance_histories ( family_id, payment_date, budget_item_id )
budget_lines ( family_id, budget_id, amount )
budget_items ( id, budget_category_id, is_custom_for_family, custom_item_family_id )
select
bi.*
from
-- pre-query a list of DISTINCT IDs from the balance history
-- and budget lines that qualify. THEN join to the rest.
( select distinct
bh.budget_item_id id
from
balance_histories bh
where
bh.family_id = 999
AND bh.payment_date >= '2021-02-01'
AND bh.payment_date <= '2021-02-28'
UNION
select
bl.budget_item_id
FROM
budget_lines bl
WHERE
bl.family_id = 999
AND bl.budget_id = 188311
AND bl.amount > 0 ) PQ
JOIN budget_items bi
on PQ.id = bi.id
AND bi.budget_category_id = 4
AND ( bi.is_custom_for_family = 0
OR
( bi.is_custom_for_family = 1
AND bi.custom_item_family_id = 999 )
)
反饋
對於許多 SQL 查詢,通常有多種方法可以獲得解決方案。 有時使用 EXISTS 效果很好,有時效果不佳。 您需要考慮數據的基數,這就是我的目標。 首先看看您要的是什么:獲取所有類別的預算項目和家庭的自定義項目是 1 或 0(全部),但如果是家庭,則只有 999 的預算項目。您對 AND/OR 的平衡是正確的. 但是,這將遍歷每條記錄,如果您有數百萬行,這就是您要掃描的內容。 只有在掃描完每一行之后,您現在才針對特定日期范圍或家庭/預算的歷史記錄進行二次查詢(針對每條符合條件的記錄)。
我的猜測是,從您的兩個 EXISTS 查詢返回的可能記錄數將會非常小。 因此,首先獲取屬於該聯合的那些 ID 的 DISTINCT 列表將是非常小的子集。 一旦找到單個“ID”,它現在將直接匹配預算項目表,並具有類別 ID/系列/自定義項目注意事項的最終過濾限制。
通過讓索引更好地匹配查詢的上下文,WHERE 子句將優化提取數據。 我已經用類似的解決方案回答了其他幾個問題,並闡明了索引以及為什么在這些問題中...... 看看例如, 這里還有另一個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.