Индекс сервера 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, ...

надеюсь, вы поняли. Я строю строку запроса в db и выполняю ее. Если я отправлю param Col1 = true, это означает, что я хочу, чтобы весь пустой Col1 был с db. Из приложения убедитесь, что я готовлю все параметры. Остальное самоочевидно, я надеюсь (но, пожалуйста, не стесняйтесь задавать любые вопросы в комментарии)!

Как сделать индекс для этой таблицы/запроса, чтобы избежать сканирования индекса или подобных «медленных» поисков? И я просто веб-разработчик, поэтому это (продвинутое) индексирование - это что-то новое для меня! Db - это SQL Server 2012.

UPDATE: usage scenario
Table will have from 100k to 10m-20m rows max. Rows will not be updated. Insert will be done in bulk of 500 (sqlbulkcopy C# class), every 5-10mins or more, when app is running (its not running always). Once every week-two some rows will be deleted (based on SomeKey col).
App will not have many users (maybe few in same time, 10 at most), so don't expect many queries/sec (1 query every 5-10 sec?), but i would like it to be fast (measured in ms, not sec).

2

2 ответы

Индекс - это компромисс. Он должен быть обновлен при изменении данных в таблице, поэтому будьте осторожны с таблицами с большим количеством INSERT и UPDATE.

В SQL Server Management Studio вы можете увидеть исполнение для вашего запроса. Есть варианты для этого в меню Query. Вы сможете увидеть, что занимает больше времени во время выполнения запроса.

Other option is Tuning advisor accessible from menu Tools > Database Engine Tuning Advisor. It will propose indexes to create.

Какая бы переменная у вас ни была в поиске, например, WHERE - хороший кандидат для индексации.

Индекс не то, что вас убьет. Вы можете играть с ним, чтобы найти лучшее решение, и вы можете вносить изменения во время производства без серьезных проблем. К сожалению решение, если вам нужен индекс, основано не только на дизайне таблицы, но и на количестве данных в этой таблице, разнообразии данных и характере операций. Вы выполняете на столе.

<Сильный> Update:

Что может вам помочь:

Производительность запросов MSDN

Настройка запросов MSDN

Referring to Your execution plan I recommend You to read part about Understanding Nested Loops Joins

Индексное сканирование обычно является результатом получения большого процента данных из данного столбца.

1
добавлено
Это реальный план запроса. imgur.com/FQcITX7 Мне не нравится эта проверка индекса. Но сейчас я стреляю в темноту и надеялся на какой-то экспертный ответ.
добавлено автор Hrvoje Hudo, источник

Лучшее решение действительно зависит от того, с какими ресурсами мы сталкиваемся: сколько строк в таблице, сколько памяти/пространства у нас есть, как часто используются динамические параметры и каков типичный шаблон использования в таблице (более подробно чем пишет?).

Моя ставка для начала была бы добавлением индекса на SomeKey , который всегда ссылается, а затем экспериментирует с добавлением Created , так как заказ всегда используется. Вы также можете улучшить логику, ставя столбцы bit , статичные (они всегда так или иначе - вы знаете все возможные значения), а затем добавляете их в индекс между SomeKey и Created .

Наконец, вы можете попробовать добавить столбцы INT в качестве столбца Включенные столбцы ключа , чтобы увидеть, смещен ли размер добавленного индекса с меньшим количеством чтения на диске.

Это для начала, потому что все зависит от вашей типичной рабочей нагрузки. Проведите тест соответствующим образом.

0
добавлено
SqlCom.ru - Стиль жизни SQL
SqlCom.ru - Стиль жизни SQL
908 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только MS SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz). Предложения в @sql_ninja

SQL_Ninja
SQL_Ninja
340 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz)