2015-09-20 70 views
0

我一直有一些麻煩,獲得單列「varchar(5)」字段可靠地使用表查找,而不是表掃描。這種情況下的生產表包含2500萬行。如同在35秒內掃描2500萬行一樣令人印象深刻,查詢應該運行得更快。內存優化的SQL Server表 - 如何確保表查找?

這裏的一個局部表的描述

CREATE TABLE [dbo].[Summaries_MO] 
(
    [SummaryId] [int] IDENTITY(1,1) NOT NULL, 
    [zipcode] [char](5) COLLATE Latin1_General_100_BIN2 NOT NULL, 
    [Golf] [bit] NULL, 
    [Homeowner] [bit] NULL, 
    [IncomeCode] [char](1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
    [Pets] [bit] NULL, 

CONSTRAINT [Summaries_MO_primaryKey] PRIMARY KEY NONCLUSTERED HASH 
(
    [SummaryId] 
)WITH (BUCKET_COUNT = 33554432), 
INDEX [ixZIP] NONCLUSTERED 
(
    [zipcode] ASC 
) 
)WITH (MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA) 

典型地,該表與包括一個查詢訪問:

SELECT ... 
      FROM SummaryTable 

      WHERE ixZIP IN (SELECT ZipCode FROM @ZipCodesForMO) 

此查詢堅持使用表掃描。我試過WITH(FORCESEEK)例如,但這只是使查詢失敗。

正如我已經研究了這個問題,我也試過:

SELECT * FROM Summaries WHERE ZipCode IN ('xxxxx', 'xxxxx', 'xxxxx') 

當我運行此查詢有64個或更少(實際的,有效的)郵政編碼,查詢使用表查找。

但是,當我給它65或更多的郵政編碼它使用表掃描。

總之,生產查詢總是使用表掃描,當我指定65個或更多的郵政編碼時,查詢也使用表掃描。

坦率地說,我想知道索引列(Latin1_General_100_BIN2不爲NULL)的數據類型是否有問題。我可能會嘗試將郵政編碼轉換爲整數以查看會發生什麼。

但我寧願知道發生了什麼,而只是隨意嘗試。

回答

0

這是有點長的評論。

首先,嘗試改寫爲join

SELECT st.* 
FROM SummaryTable st JOIN 
    @ZipCodesForMO z 
    ON st.ixZIP = z.ZipCode; 

之所以這樣做是JOIN■找優化比IN更多的機會。

我認爲SQL Server更喜歡全表掃描的原因是因爲每個索引seek都需要跟一個頁面查找來獲取表中其餘的列。這使工作量增加了一倍。你有狹窄的記錄,所以即使2500萬行可能適合3萬頁左右的頁面。

我認爲64的臨界值太小。但是,一個10000個郵政編碼的清單需要閱讀大約10,000個左右的頁面。通過索引查找,會 - 以非常粗略的方式 - 將努力加倍。因此,對錶格進行掃描可能會有相似或更好的性能(順序掃描會比隨機掃描顯着優化)。

0

最小尺寸:
使用SMALLINT的郵政編碼
考慮TINYINT爲IncomeCode

使用#TEMP爲ZipCodesForMO與PK
而聯接

SELECT ... 
FROM SummaryTable 
JOIN #zipCodesForMOWHERE 
    on SummaryTable.zipcode = #zipCodesForMOWHERE.ZipCode