2016-07-10 73 views
1

我不是SQL中的專業人員:) 存在非常關鍵的性能問題。 以下是與問題直接相關的信息。PostgreSQL多個'WHERE'條件(1000+)請求

我在我的DB-表condos和表goods有2個表。

condos有字段:

  • ID(PK)
  • 城市
  • 國家

表項目:

  • ID(PK)
  • 多個領域不涉及發行
  • condo_id(FK)

我有condos表1000+實體和items表1000+。

的問題是我怎麼物品進行搜索

目前,它是:

例如,我想所有的物品爲city = Sydney

  1. 執行SELECT condos.condo_id FROM public.condos WHERE city = 'Sydney'
  2. 爲我在步驟1中獲得的每個condo_id製作一個SELECT * FROM public.items WHERE item.condo_id = ?

問題是,一旦我在condos表中獲得了1000多個實體,則對於屬於「悉尼」的每個condo_id,該請求將執行1000次以上。而這個請求的執行需要2分鐘以上,這是一個關鍵的性能問題。

所以,的問題是:

什麼是對我進行這樣的搜索的最佳方式?我應該把1000+身份證放在單個WHERE請求中嗎?要麼?

對於添加信息,我使用PostgreSQL 9.4Spring MVC

+4

您知道表連接的區域?從你的問題看,你不是,如果不是,你需要了解他們。這正是聯接想要解決的問題類型。 –

回答

1

從本質上講,你需要的是消除N + 1查詢,並在同一時間確保您的城市字段被索引。你有3種機制可以去。其中一個你已經收到的其他答案之一就是SUBSELECT方法。除了這種方法你還有兩個。

你可以使用你說什麼:

SELECT condos.condo_id FROM public.condos WHERE city = 'Sydney' 

SELECT * 
FROM public.items 
WHERE items.condo_id IN (up to 1000 ids here) 

爲什麼我指出了到1000的原因是因爲一些SQL商有侷限性。

你也可以做加盟的方式來消除N + 1選擇

SELECT * 
FROM public.items join public.condos on items.condo_id=condos.condo_id and condos.city='Sydney' 

是現在什麼在3個查詢之間的區別。

部分選擇查詢的優點是您可以一次獲得所有內容。 缺點是如果你有太多元素的性能可能會受到影響:

簡單的優點條款。用途不同解決了N + 1點的問題, 缺點可能會導致一些額外的查詢比子選擇

連接查詢利弊,你可以初始化一個去兩個公寓和Item。 缺點導致公寓方面的一些數據重複

如果我們看看像Hibernate這樣的框架,我們可以發現,在大多數情況下,使用獲取策略或者使用IN策略。子選擇很少使用。

此外,如果你有關鍵性能,你可能會考慮閱讀記憶中的一切,並從那裏提供服務。從這兩張表格的內容來看,將它上傳到地圖應該相當容易。

可以解決你的N + 1查詢問題的有效一切都在你的情況下,如果我們談論的僅有2次1000個查詢的解決方案。所有三個選項都是解決方案

+0

謝謝你最滿的答案。還有一個小問題 - 如果我還有多個'WHERE'參數,我應該在'AND'運算符中指定它們嗎? like:'和condos.city ='悉尼'和item.name ='item1'和item.price = 1999'等等(如果我使用JOIN查詢) – user1935987

+0

理論上,你可以直接將它們放入連接子句或在where子句之後。我知道,對於不同的數據庫提供商,性能可能會有一些小的差異,但您必須自己測試。因此,無論是在where子句中用AND條件指定它們,還是用AND將它們直接放入JOIN子句中。 –

+0

我想有一個錯誤'public.items加入public.condos on item.condo_id = condos.condo_id'需要'items.condo_id = condos.condo_id'。但通常看起來像工作。謝謝! – user1935987

0

你可以在第二個查詢使用第一個查詢作爲子查詢中的in操作:

SELECT * 
FROM public.items 
WHERE item.condo_id IN (SELECT condos.condo_id 
         FROM public.condos 
         WHERE city = 'Sydney') 
2

使用表join來執行查詢,以便您不需要執行其他查詢。你的情況,你可以通過condo_id加入condositems是這樣的:

SELECT i.* 
FROM public.items i join public.condos c on i.condo_id = c.condo_id 
WHERE c.city = 'Sydney' 

注意,性能調優是董事會的話題。它可以因環境而異,取決於您如何在表格中構造數據以及如何在代碼中組織數據。

下面是一些其他的建議,也可能會有幫助:

嘗試索引添加到您使用排序和搜索領域,例如city in condos and condo_id in items。有一個很好的answer來解釋如何索引工作。

我還建議您執行EXPLAIN爲您的查詢設計查詢計劃,以確定是否存在可能導致性能問題的全表搜索。

希望這可以幫助。

+0

這與問題沒有多大關係,除了連接部分。 –

+0

@SamiKuhmonen OP說他有一個嚴重的性能問題,執行一個請求需要2分鐘以上的時間。因此,我提供了有關如何更好地解決問題的建議。我錯過了什麼嗎? – Wilson