簡體   English   中英

如何避免在聯合中兩次運行昂貴的子查詢

[英]How to avoid running an expensive sub-query twice in a union

我想合並兩個查詢。 這兩個查詢都使用對數據集的內部聯接,該聯接非常難以計算,但是兩個查詢的數據集查詢都相同。 例如:

SELECT veggie_id
FROM potatoes
INNER JOIN ( [...] ) massive_market
    ON massive_market.potato_id=potatoes.potato_id
UNION
SELECT veggie_id
FROM carrots
INNER JOIN ( [...] ) massive_market
    ON massive_market.carrot_id=carrots.carrot_id

其中[...]對應於需要一秒鍾計算的子查詢,並返回至少包含胡蘿卜和土豆的行。

我想避免在總體查詢中兩次查詢Massive_market [...]

最好的方法是什么?

如果該子查詢需要多於一秒鍾的時間運行,那么我想說這是一個索引問題,而不是查詢本身(當然,在沒有看到該查詢的情況下,這在某種程度上是推測,我建議也發布該查詢) 。 以我的經驗,9/10緩慢的查詢問題歸結為數據庫索引不正確。

確保已將veggie_id,potato_id和胡蘿卜_id索引

另外,如果您在Massive_market子查詢中使用任何聯接,請確保對正在執行聯接的列也進行了索引。

編輯

如果索引已正確完成,那么我想到的唯一其他解決方案是:

CREATE TEMPORARY TABLE tmp_veggies (potato_id [datatype], carrot_id [datatype]);

INSERT IGNORE INTO tmp_veggies (potato_id, carrot_id) select potatoes.veggie_id, carrots.veggie_id from [...] massive_market 
    RIGHT OUTER JOIN potatoes on massive_market.potato_id = potatoes.potato_id 
    RIGHT OUTER JOIN carrots on massive_market.carrot_id = carrots.carrot_id;
SELECT carrot_id FROM tmp_veggies
UNION
SELECT potato_id FROM tmp_veggies;

這樣,您已經反轉了查詢,因此它只運行一次大規模子查詢,並且UNION正在臨時表上發生(臨時表將自動刪除, 但直到關閉連接后才會刪除),因此您可能希望手動刪除表)。
您可以將所需的任何其他列添加到CREATE TEMPORARY TABLESELECT語句中

目的是將所有重復的查詢字符串從需要重復查詢字符串的查詢字符串列表中拉出。 因此,我將土豆和胡蘿卜放在一個聯合子查詢中,然后將Massive_market放在此統一之外。

這似乎很明顯,但是我的問題來自一個更為復雜的查詢,而實施此策略所需的工作在我的案例中涉及更多。 對於上述問題中的簡單示例,這可以通過以下方式解決:

SELECT veggie_id 
FROM (
  SELECT veggie_id, potato_id, NULL AS carrot_id FROM potatoes
  UNION
  SELECT veggie_id, NULL AS potato_id, carrot_id FROM carrots
) unionized
INNER JOIN ( [...] ) massive_market
  ON massive_market.potato_id=unionized.potato_id 
    OR massive_market.carrot_id=unionized.carrot_id

暫無
暫無

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

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