参数化查询的SQL Server索引

时间:2013-02-07 12:39:16

标签: sql sql-server indexing sql-server-2012

我想为sql查询创建最佳索引。用户可以在UI上选择从中构建查询的选项。这是表格和查询:

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中构建查询字符串并执行它。如果我发送参数Col1 = true,这意味着我想要db中的所有空Col1。从应用程序我确保我准备所有参数。我希望休息是不言自明的(但请随意在评论中提出任何问题)!

如何为此表/查询创建索引,以避免索引扫描或类似的“慢”搜索?而且,我只是一个Web开发人员,所以这个(高级)索引对我来说是新的东西! Db是SQL Server 2012.

更新:使用方案
表格最大行数为100k至10m-20m。行不会更新。当应用程序运行时(或者总是不运行),插入将以500(sqlbulkcopy c#类)的大量进行,每5-10分钟或更长时间。每周一次 - 两行将被删除(基于SomeKey col) 应用程序将不会有很多用户(可能很少在同一时间,最多10个),所以不要期望很多查询/秒(每5-10秒1次查询?),但我希望它快(以毫秒为单位) ,而不是秒)。

2 个答案:

答案 0 :(得分:1)

指数是一种权衡。必须更新表中的数据更改,因此请注意包含大量INSERT和UPDATE的表。

在SQL Server Management Studio中,您可以看到查询的执行播放。 “查询”菜单下有选项。您将能够查看在查询执行期间花费大量时间的内容。

其他选项是可从菜单工具>访问Tuning顾问程序。数据库引擎优化顾问。它将提出创建索引。

您在WHERE等搜索中拥有的变量是一个很好的索引候选者。

索引不会杀死你。您可以使用它来找到最佳解决方案,您可以在生产过程中进行更改而不会出现重大问题。不幸的是,如果您需要索引,则决定不仅基于表格设计,还基于此表格中的数据量,数据多样性以及您在桌面上执行的操作性质。

<强>更新

有什么可以帮到你:

MSDN Query Performance

MSDN Query Tuning

参考您的执行计划,我建议您阅读有关Understanding Nested Loops Joins

的部分内容

索引扫描通常是从给定列中检索大部分数据的结果。

答案 1 :(得分:0)

最佳解决方案实际上取决于我们正在处理的资源 - 表包含多少行,可用的内存/空间,动态参数的使用频率以及表中的典型使用模式(读取的次数多于写入次数?)。

我开始的赌注是在SomeKey添加始终引用的索引,然后尝试添加Created,因为总是也会使用排序。您还可以通过使bit列过滤静态(它们始终是这样或那样 - 您知道所有可能的值)然后将它们添加到SomeKey和{{1}之间的索引中来改进逻辑}。

最后,您可以尝试添加Created列作为键的包含的列,以查看添加的索引大小是否以较少的磁盘读取偏移。

这是初学者,因为一切都取决于你的典型工作量。做相应的测试。