2010-04-02 65 views
3

我有了如下表SQL數據庫:SQL查詢 - 20密爾記錄 - 最佳實踐返回信息

 
Table: PhoneRecords 
-------------- 
ID(identity Seed) 
FirstName 
LastName 
PhoneNumber 
ZipCode 

很簡單直接的表。這張表有超過2000萬條記錄。我正在尋找最好的方法來完成基於表格區域代碼的記錄。例如這裏是我所做的一個示例查詢。

SELECT phonenumber, firstname 
FROM [PhoneRecords] 
WHERE (phone LIKE '2012042%') OR 
     (phone LIKE '2012046%') OR 
     (phone LIKE '2012047%') OR 
     (phone LIKE '2012083%') OR 
     (phone LIKE '2012088%') OR 
     (phone LIKE '2012841%') 

正如你可以看到這是一個醜陋的查詢,但它會完成這項工作(我是不是遇到了超時問題)

誰能告訴我要速度/優化的最好方法做上面的查詢來顯示結果?目前上面的查詢需要大約2個小時才能完成9gb 1600mhz內存,i7 930 quadcore OC'd 4.01ghz。我顯然擁有執行這樣的查詢所需的計算機能力,但查詢仍然需要很長時間。

+1

你可以提供表上索引的詳細信息嗎? – 2010-04-02 09:04:18

回答

6

您可能缺少電話號碼列上的索引。

CREATE INDEX IX_PHONERECORDS_PHONENUMBER_FIRSTNAME 
    ON dbo.PhoneRecords (PhoneNumber) INCLUDE (FirstName) 

如果沒有幫助,發佈execution planCTRL+M)。

+2

感謝大家的快速回復。手機沒有編入索引,但我現在設置它試圖運行查詢(使用Union All而不是OR)來查看它是否更快。我會發布我的調查結果,希望任何遇到這個問題的人都能夠解決這個問題。 – eqiz 2010-04-02 09:24:46

+0

@eqiz:當你發佈信息時,我也會很想知道單獨添加索引是否足夠,優化程序是否可以處理您的OR,或者如果查詢重寫有助於優化程序選擇最佳計劃。 – 2010-04-02 09:37:24

+0

如果使用'union all'會比'或'子句表現更好(或更差),我會感到驚訝 – 2010-04-02 10:06:41

5

首先,您需要列phone上的索引。如果你沒有,添加它。

如果它仍然運行緩慢,您可以嘗試使用UNION ALL而不是OR,因爲優化器可以更輕鬆地使用它。這是有效的,因爲你構建你的條件的方式可以保證結果是不同的。因此,您的查詢可以被重寫爲:

SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012042%' 
UNION ALL 
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012046%' 
UNION ALL 
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012047%' 
UNION ALL 
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012083%' 
UNION ALL 
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012088%' 
UNION ALL 
SELECT phonenumber, firstname FROM [PhoneRecords] WHERE phone LIKE '2012041%' 

此查詢應該能夠使用索引有效地運行。

您應該在運行實際查詢之前查看執行計劃,並確保沒有TABLE SCAN或INDEX SCAN。

+0

聯合等同於使用OR語句。 SQL查詢優化器不會以任何方式使用相同的計劃嗎? – uriDium 2010-04-02 09:08:28

+0

解釋?你不覺得與MySQL混淆嗎? – 2010-04-02 09:13:59

+0

對不起,是的......混淆了!你是對的 - SQL Server沒有這個功能。對於SQL Server來說,查看計劃的最簡單方法是在SSMS中。有一個按鈕「顯示預計執行計劃」。 – 2010-04-02 09:26:01

2

你有沒有索引?第一步是在PhoneNumber列中添加一個索引。如果這還不夠(我不知道索引列中部分字符串搜索的具體細節),我會建議添加另一個名爲「AreaCode」的列,該列可以從PhoneNumber列自動計算。然後你可以在AreaCode列上添加一個索引。

2

第一個也是很明顯的問題是你有索引嗎?如果您要查詢它,您至少需要在電話號碼上創建索引。您應該創建一個覆蓋索引,其中包含所需的字段以及where子句中的字段,這樣計算機在索引中找到行後就不必浪費時間來獲取所需的信息。很明顯,反過來說,索引越大,查詢越慢。

2

你可以分割你的電話號碼列:

然後[區號] [電話號碼],如果該查詢是在應用程序中「最重要的」這個表和比例返回的行/總行是高的,在[地區代碼]上添加一個CLUSTERED索引,否則添加一個標準索引。

您也可以保留電話號碼列並直接編入索引,這取決於您的應用程序。

1

首先,我會將電話欄拆分爲「區號」和「電話號碼」。

此外,我會將此數字轉換爲int;索引將執行得更快。

AreaCode = 2012042 

要快很多,然後

PhoneNumber LIKE '2012042%' 
0

http://igoro.com/archive/precomputed-view-a-cool-and-useful-sql-pattern

創建物化視圖,其中包括電話號碼的前n個數字,因爲它是自己的專欄。然後,您可以根據區號列查詢幷包含名稱。預先計算區域代碼,使其不必在每次選擇時完成。如果可以幫助,請不要使用or操作符。使用聯合來幫助查詢計劃使用索引。

實際上,您正在運行的查詢將執行20,000,000次x次比較,其中x是您每次執行選擇時搜索的區號的數量。通過查詢一個確切索引的列,你根本不需要去查看錶格,索引可以以有效的方式搜索O(log n)我認爲。

1

即使您正在執行表掃描(並且即使您有索引,也可能發生這種情況,但如果選擇性較低),您的查詢應該以比2小時更快的方式執行。如果與其他查詢掃描的其他表無關,並且sqlserver max內存足夠大,則表的大小足以完全適合sql服務器緩衝池。所以雖然你可以做一些技巧,如添加索引或拆分區域+電話的電話號碼,你應該調查sql server的配置以及你的系統配置。