2013-02-07 69 views
2

我想爲sql查詢創建最佳索引。用戶可以從構建查詢的用戶界面中選擇選項。下面是表和查詢:參數化查詢的Sql服務器索引

CREATE TABLE [dbo].[MyTable](
    [Id] [nvarchar](32) NOT NULL, 
    [SomeKey] [int] NOT NULL, 
    [Col1] [nvarchar](max) NULL, 
    [Col2] [nvarchar](max) NULL, 
    [NumCol1] [int] NOT NULL, 
    [NumCol2] [int] NOT NULL, 
    [BitCol1] [bit] NOT NULL, 
    [BitCol2] [bit] NOT NULL, 
    [Created] [datetime] NOT NULL 
CONSTRAINT [PK_dbo.MyTable] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

和查詢是在這裏(SP):

ALTER PROCEDURE [dbo].[MyTable] 
@SomeKey INT,@Col1 BIT,@Col2 BIT,@BitCol1 BIT,@BitCol2 BIT, 
@NumCol1 INT,@NumCol2 INT,@offset INT,@take INT 
AS 
DECLARE @sql NVARCHAR(MAX), @paramlist nvarchar(4000) 
SET @sql = 'SELECT [Id],[SomeKey],[Col1],[Col2],[NumCol1],[NumCol2],[BitCol1],[BitCol2], FROM MyTable WHERE SomeKey = @SomeKey' 
IF @NumCol1 IS NOT NULL SELECT @sql = @sql + ' AND NumCol1 = @NumCol1' 
IF @NumCol2 IS NOT NULL SELECT @sql = @sql + ' AND (NumCol2 > @NumCol2)' 
IF @Col1 IS NOT NULL SELECT @sql = @sql + ' AND (Col1 = '''' OR Col1 IS NULL)' 
IF @Col2 IS NOT NULL SELECT @sql = @sql + ' AND (Col2 = '''' OR Col2 IS NULL)' 
IF @BitCol1 IS NOT NULL SELECT @sql = @sql + ' AND BitCol1 = 1' 
IF @BitCol2 IS NOT NULL SELECT @sql = @sql + ' AND BitCol2 = 1' 
SELECT @sql = @sql + ' ORDER BY Created OFFSET @offset ROWS FETCH NEXT @take ROWS ONLY' 
SELECT @paramlist = '@SomeKey INT, @Col1 INT, ....' 
EXEC sp_executesql @sql, @paramlist, @SomeKey, @Col1, @Col2, ... 

希望你明白了吧。我建立查詢字符串在數據庫中,並執行它。如果我發送參數Col1 = true,這意味着我想從數據庫中的所有空Col1。從應用程序我確保我準備所有參數。休息是不言自明的,我希望(但請隨時在評論中提出任何問題)!

如何爲此表/查詢製作索引,以避免索引掃描或類似的「緩慢」搜索?而且,我只是一個Web開發人員,所以這種(高級)索引對我來說是新事物! db是SQL Server 2012的

更新:使用場景
表將有10萬,從10米-20M行最大。行將不會更新。當應用程序正在運行時(它不會始終運行),插入操作將在散列500(sqlbulkcopy c#類)中每隔5-10分鐘或更長時間完成。每週一次 - 兩行將被刪除(基於SomeKey col)。
應用程序不會有很多用戶(可能很少有人在同一時間,最多10個),所以不要期望許多查詢/秒(每5-10秒一個查詢?),但我希望它很快(測量以毫秒爲單位,而不是秒)。

回答

1

索引是一個權衡。必須更新表中的數據更改,因此請注意包含大量INSERT和UPDATE的表。

在SQL Server Management Studio中,您可以看到針對您的查詢執行遊戲。查詢菜單下有這些選項。您將能夠看到執行查詢時需要花費大量時間。

其他選項是Tuning advisor,可從菜單Tools> Database Engine Tuning Advisor訪問。它會建議創建索引。

無論您在像WHERE這樣的搜索中使用哪種變量都是一個很好的候選項。

索引不是會殺了你的東西。您可以使用它來找到最佳解決方案,並且您可以在生產過程中進行更改而不會出現重大問題不幸的是,您是否需要索引的決定不僅基於表格設計,還取決於該表格中的數據量,數據多樣性和您在表格上執行的操作性質。

更新:

什麼可以幫助您:

MSDN Query Performance

MSDN Query Tuning

參考你的執行計劃,我建議你到約Understanding Nested Loops Joins

指數掃描讀出部分通常是水庫超過從給定列中檢索大部分數據。

+0

這是實際的查詢計劃,我有http://imgur.com/FQcITX7我不喜歡這個索引掃描。但是我現在在黑暗中拍攝,希望得到某種專家的回答。 –

0

的最佳解決方案實際上取決於我們面對的是什麼樣的資源 - 該表有多少行認爲,我們有多少內存/存儲空間大小,頻率的動態參數的使用,以及什麼是對的典型使用模式表(讀取比寫入更多?)。

我打賭開始時會在SomeKey上加上總是被引用的索引,然後嘗試添加Created,因爲總是使用排序。您也可以通過使bit列過濾靜態提高邏輯(他們總是一種方式或其他 - 你知道所有可能的值),然後將那些SomeKeyCreated之間的指數。

最後,您可以嘗試添加INT列作爲關鍵的包含的列,看是否添加索引大小與較少的磁盤讀取偏移。

這對於初學者,因爲一切都取決於你的典型的工作負載。做相應的測試。