簡體   English   中英

使用左外連接進行慢查詢並且為空條件

[英]Slow query with left outer join and is null condition

我有一個簡單的查詢(postgresql,如果這很重要),它檢索some_user的所有項目,不包括她在心願單上的項目

select i.* 
from core_item i 
left outer join core_item_in_basket b on (i.id=b.item_id and b.user_id=__some_user__)
where b.on_wishlist is null;

以上查詢運行在~50000ms(是的,數字是正確的)。 如果我刪除“b.on_wishlist為null”條件或使其“b.on_wishlist is not null”,則查詢將在大約50ms內運行(相當大的變化)。

該查詢具有更多的連接和條件,但這是無關緊要的,因為只有這一個減慢了它。

有關數據庫大小的一些信息:

  • core_items有~10,000條記錄
  • core_user有~5000條記錄
  • core_item_in_basket有~2.000
  • 記錄(其中約50%的on_wishlist = true,其余為null)

我在這兩個表上沒有任何索引(除了id和外鍵)。

問題是: 我該怎么做才能讓這個更快? 我自己今晚有一些想法可以查看,但如果可能的話,我希望你們能幫忙。

謝謝!

嘗試使用不存在:

select i.* 
from   core_item i 
where  not exists (select * from core_item_in_basket b where i.id=b.item_id and b.user_id=__some_user__)

很抱歉添加第二個答案,但stackoverflow不允許我正確格式化評論,因為格式化是必不可少的,我必須發布答案。

幾種選擇:

  1. CREATE INDEX q ON core_item_in_basket(user_id,item_id)WHERE on_wishlist為null;
  2. 相同的索引,但改變其中列的順序。
  3. SELECT i。* FROM core_item i WHERE i.id not in(select item_id FROM core_item_in_basket WHERE on_wishlist為null AND user_id = __some_user__); (此查詢可以從第1點的索引中受益,但不會從索引#2中受益。
  4. SELECT * from core_item where id in(select id from core_item EXCEPT select item_id FROM core_item_in_basket WHERE on_wishlist為null AND user_id = __some_user__);

讓我們知道結果 :)

您可能想要更多地解釋此查詢的目的 - 正如某些技術所做的那樣,有些技術沒有意義,具體取決於用例。

你多久運行一次?

它是僅為1個用戶運行,還是在某種循環中為所有用戶運行?

做:解釋分析並將輸出放在explain.depesz.com上,這樣你就會明白它為什么這么慢。

您是否嘗試在on_wishlist上添加索引

似乎需要為查詢中的每一行檢查此列。 如果您的表很大,這可能會對查詢速度產生很大影響。

當您將on_wishlist條件放在where子句中時,這將導致它(取決於查詢計划器決定的內容)在執行連接后進行評估,因此必須對連接產生的每一行進行比較。 core_itemscore_item_in_basket表都非常大,並且您沒有該列的索引,因此查詢優化器幾乎沒有,這可能會導致查詢時間過長。

core_user的大小應該沒有影響(因為它沒有在查詢中引用)。

暫無
暫無

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

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