具有相同列的多个索引建议
Multiple index suggestions with same columns
我有一个 table 每小时收到数千个 select 查询。 SQL 服务器建议我创建四个索引,每个索引估计有 99% 的改进:
- [表名]([代码限定符])(查询 3)
- [表名]([行代码]、[代码限定符]、[行号_])(查询 1)
- [表名]([行代码]、[代码限定符]、[状态])
- [表名]([行代码]、[代码限定符]、[状态]、[行号_])(查询 2)
类型如下:
- [代码限定符]
nvarchar(20)
- [线路代码]
nvarchar(20)
- [状态]
tinyint
- [行号_]
int
table 没有更新那么频繁,select 查询似乎超过 updates/inserts 大约 1000 比 1。那么问题是,我应该创建所有索引还是创建一个索引有助于改善所有查询?如果我想一次添加一个,并在每次添加后检查性能,我应该按什么顺序添加它们,应该单独添加还是组合添加?如果问题无法回答,除了反复试验之外,我还能做些什么来找出答案,这不是一种选择,因为我自己无法修改这些。
编辑(建议链接到索引的查询):
查询 1:
SELECT TOP (1)
* --enumerated, but still all columns selected
FROM
"TableName" WITH(UPDLOCK)
WHERE
("Line Code"=@0 AND "Code Qualifier"=@1 AND "Line No_"=@2)
ORDER BY
"Message Batch Number" ASC,
"Message Line Number" ASC OPTION(OPTIMIZE FOR UNKNOWN)
查询 2:
SELECT
* --enumerated, but still all columns selected
FROM
"TableName" WITH(UPDLOCK)
WHERE
("Line Code"=@0 AND "Code Qualifier"=@1 AND "Status"=@2 AND "Line No_"=@3)
ORDER BY
"Message Batch Number" ASC,
"Message Line Number" ASC OPTION(OPTIMIZE FOR UNKNOWN, FAST 50)
查询 3:
UPDATE
"TableName"
SET
"Status"=@0
WHERE ("Code Qualifier"=@1)
因此,其中一个实际上是更新。这也每小时执行多次,但不像 select 那样频繁。我无法立即找到这些查询之一,但希望这些可以。
编辑 2(现有索引):
所以这些已经到位,但几乎没有在任何查询中使用:
- [消息批号] (int),[消息行号] (int)(集群)
- [状态]、[消息批号]、[消息行号]
- [控件引用] (nvarchar(30)、[消息批号]、[消息行号]
孤立地查看查询,理想情况下您需要以下索引:
查询 1
CLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_],
[Message Batch Number], [Message Line Number])
-- first three columns in any order
查询 2
CLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_], Status,
[Message Batch Number], [Message Line Number])
-- first four columns in any order
前几列的顺序应该是最有选择性的。
您可以通过删除 Status
来合并前两个索引。缺点是它不能被查找,但因为它是一个聚集索引,所以不会那么重要。如果你想要一个非聚集索引,那么 all 其他选定的列应该在 INCLUDE
.
所以最终需要的索引是:
CLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_],
[Message Batch Number], [Message Line Number])
-- first three columns in any order
-- you can change it to NONCLUSTERED by using INCLUDE
NONCLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_],
[Message Batch Number], [Message Line Number])
INCLUDE (Status, anyOtherColumnsHere)
对于查询 3 你只需要,
NONCLUSTERED INDEX ([Code Qualifier]) INCLUDE (Status)
如果您使用的是诸如 Linq2SQL 之类的 ORM(给定参数名称,这似乎是这样),请确保传入正确的变量数据类型和长度,否则将不会使用索引
我设法通过复制我们的生产数据库来测试这个,运行 这些查询在有和没有不同索引的循环中。令人惊讶的是,似乎只在 Code Qualifier
上添加非聚集索引可以将所有查询的执行时间降低到几乎为零,并进行几十次迭代。因此,在回答我自己的问题时,单个列的单个索引似乎足以满足实际目的。
我有一个 table 每小时收到数千个 select 查询。 SQL 服务器建议我创建四个索引,每个索引估计有 99% 的改进:
- [表名]([代码限定符])(查询 3)
- [表名]([行代码]、[代码限定符]、[行号_])(查询 1)
- [表名]([行代码]、[代码限定符]、[状态])
- [表名]([行代码]、[代码限定符]、[状态]、[行号_])(查询 2)
类型如下:
- [代码限定符]
nvarchar(20)
- [线路代码]
nvarchar(20)
- [状态]
tinyint
- [行号_]
int
table 没有更新那么频繁,select 查询似乎超过 updates/inserts 大约 1000 比 1。那么问题是,我应该创建所有索引还是创建一个索引有助于改善所有查询?如果我想一次添加一个,并在每次添加后检查性能,我应该按什么顺序添加它们,应该单独添加还是组合添加?如果问题无法回答,除了反复试验之外,我还能做些什么来找出答案,这不是一种选择,因为我自己无法修改这些。
编辑(建议链接到索引的查询):
查询 1:
SELECT TOP (1)
* --enumerated, but still all columns selected
FROM
"TableName" WITH(UPDLOCK)
WHERE
("Line Code"=@0 AND "Code Qualifier"=@1 AND "Line No_"=@2)
ORDER BY
"Message Batch Number" ASC,
"Message Line Number" ASC OPTION(OPTIMIZE FOR UNKNOWN)
查询 2:
SELECT
* --enumerated, but still all columns selected
FROM
"TableName" WITH(UPDLOCK)
WHERE
("Line Code"=@0 AND "Code Qualifier"=@1 AND "Status"=@2 AND "Line No_"=@3)
ORDER BY
"Message Batch Number" ASC,
"Message Line Number" ASC OPTION(OPTIMIZE FOR UNKNOWN, FAST 50)
查询 3:
UPDATE
"TableName"
SET
"Status"=@0
WHERE ("Code Qualifier"=@1)
因此,其中一个实际上是更新。这也每小时执行多次,但不像 select 那样频繁。我无法立即找到这些查询之一,但希望这些可以。
编辑 2(现有索引): 所以这些已经到位,但几乎没有在任何查询中使用:
- [消息批号] (int),[消息行号] (int)(集群)
- [状态]、[消息批号]、[消息行号]
- [控件引用] (nvarchar(30)、[消息批号]、[消息行号]
孤立地查看查询,理想情况下您需要以下索引:
查询 1
CLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_],
[Message Batch Number], [Message Line Number])
-- first three columns in any order
查询 2
CLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_], Status,
[Message Batch Number], [Message Line Number])
-- first four columns in any order
前几列的顺序应该是最有选择性的。
您可以通过删除 Status
来合并前两个索引。缺点是它不能被查找,但因为它是一个聚集索引,所以不会那么重要。如果你想要一个非聚集索引,那么 all 其他选定的列应该在 INCLUDE
.
所以最终需要的索引是:
CLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_],
[Message Batch Number], [Message Line Number])
-- first three columns in any order
-- you can change it to NONCLUSTERED by using INCLUDE
NONCLUSTERED INDEX ([Line Code], [Code Qualifier], [Line No_],
[Message Batch Number], [Message Line Number])
INCLUDE (Status, anyOtherColumnsHere)
对于查询 3 你只需要,
NONCLUSTERED INDEX ([Code Qualifier]) INCLUDE (Status)
如果您使用的是诸如 Linq2SQL 之类的 ORM(给定参数名称,这似乎是这样),请确保传入正确的变量数据类型和长度,否则将不会使用索引
我设法通过复制我们的生产数据库来测试这个,运行 这些查询在有和没有不同索引的循环中。令人惊讶的是,似乎只在 Code Qualifier
上添加非聚集索引可以将所有查询的执行时间降低到几乎为零,并进行几十次迭代。因此,在回答我自己的问题时,单个列的单个索引似乎足以满足实际目的。