我有一个简单的表,由列和索引组成,如下所示。
这是我在推荐sql数据库引擎优化顾问时创建的索引。它包含所有列。
CREATE NONCLUSTERED INDEX [_dta_index_PROPOSAL_PROCESS_12_13243102__K2_K7_K1_3_4_5_6_8_9_10] ON [dbo].[PROPOSAL_PROCESS]
(
[PROPOSAL_ID] ASC,
[IS_DELETED] ASC,
[ID] ASC
)
INCLUDE ( [CREATOR_USER_ID],
[CREATION_TIME],
[LAST_UPDATER_USER_ID],
[LAST_UPDATE_TIME],
[CURRENT_PROPOSAL_OBJECT],
[INTERFACTORING_XML],
[OMDM_OUTPUT_XML]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
每当我添加图片中检查的列时,执行时间就会严重增加。这是我的测试结果。
如果我不包含上述列。
SET STATISTICS IO ON
SET STATISTICS TIME ON
CHECKPOINT;
GO
DBCC DROPCLEANBUFFERS;
GO
DECLARE @DynamicFilterParam_000001 bit = 0,
@DynamicFilterParam_000002 bit = null,
@EntityKeyValue1 int = 4419;
SELECT
[Extent1].[ID] AS [ID],
--[Extent1].[CURRENT_PROPOSAL_OBJECT] AS [CURRENT_PROPOSAL_OBJECT],
--[Extent1].[INTERFACTORING_XML] AS [INTERFACTORING_XML],
--[Extent1].[OMDM_OUTPUT_XML] AS [OMDM_OUTPUT_XML],
[Extent1].[PROPOSAL_ID] AS [PROPOSAL_ID],
[Extent1].[CREATOR_USER_ID] AS [CREATOR_USER_ID],
[Extent1].[CREATION_TIME] AS [CREATION_TIME],
[Extent1].[LAST_UPDATER_USER_ID] AS [LAST_UPDATER_USER_ID],
[Extent1].[LAST_UPDATE_TIME] AS [LAST_UPDATE_TIME],
[Extent1].[IS_DELETED] AS [IS_DELETED]
FROM [dbo].[PROPOSAL_PROCESS] AS [Extent1]
WHERE (([Extent1].[IS_DELETED] = @DynamicFilterParam_000001) ) AND ([Extent1].[PROPOSAL_ID] = @EntityKeyValue1);
(54行(s)受影响) 表' PROPOSAL_PROCESS'。扫描计数1,逻辑读取58,物理读取2,预读读取55,lob逻辑读取0,lob物理读取0,lob预读读取0。
(1行受影响)
SQL Server执行时间: CPU时间= 31 ms,已用时间= 16 ms。 SQL Server解析和编译时间: CPU时间= 0 ms,已用时间= 0 ms。
SQL Server执行时间: CPU时间= 0 ms,经过时间= 0 ms。
如果我将CURRENT_PROPOSAL_OBJECT添加到上一个查询的select子句
(54行(s)受影响) 表' PROPOSAL_PROCESS'。扫描计数1,逻辑读取58,物理读取2,预读读取55,lob逻辑读取0,lob物理读取0,lob预读读取0。
(1行受影响)
SQL Server执行时间: CPU时间= 0 ms,已用时间= 545 ms。 SQL Server解析和编译时间: CPU时间= 0 ms,已用时间= 0 ms。
如果我添加INTERFACTORING_XML以选择先前查询的子句
(54行(s)受影响) 表' PROPOSAL_PROCESS'。扫描计数1,逻辑读取58,物理读取2,预读读取55,lob逻辑读取1822,lob物理读取376,lob预读读取0。
(1行受影响)
SQL Server执行时间: CPU时间= 47 ms,已用时间= 2415 ms。 SQL Server解析和编译时间: CPU时间= 0 ms,已用时间= 0 ms。
如果我将CURRENT_PROPOSAL_OBJECT添加到上一个查询的select子句
(54行(s)受影响) 表' PROPOSAL_PROCESS'。扫描计数1,逻辑读取58,物理读取2,预读读取55,lob逻辑读取5048,lob物理读取944,lob预读读取0。
(1行受影响)
SQL Server执行时间: CPU时间= 47 ms,已用时间= 6912 ms。 SQL Server解析和编译时间: CPU时间= 0 ms,已用时间= 0 ms。
所以在一天结束的时候我面临6912毫秒秒。这种糟糕表现的原因是什么?
我错过了创建一些索引吗?这是因为糟糕的设计源于将大尺寸的nvarchar放在同一张桌子上?
提前致谢
编辑:Here是重新生成问题的脚本。我试图在sql-fiddle上创建相同的问题,但它甚至没有插入一行。
编辑2:如果我在select子句中包含所有列,并且只提供另一个使查询返回2行的提议ID,则执行时间通常大约保持在100 ms。查询执行时间变得越来越糟,这取决于返回的增加rows.No与索引的连接。
答案 0 :(得分:1)
NVARCHAR(max)是旧ntext数据类型的替代。
ntext将始终将其信息存储为行外的BLOB。在可能的情况下,NVARCHAR(max)将尝试将信息存储在该行中。如果由于尺寸不合适,那么它会将文本存储在BLOB中。
SQL Server将处理从BLOB到可读nvarchar文本的转换,但不是免费的。每次SQL Server必须离开行时,都会产生额外的开销。
调优顾问实际上是在告诉你这个。比较第一个查询(0)上的lob(大对象)读取次数,以及后面的参数和引用nvarchar(max)字段的数量。
答案 1 :(得分:1)
不要把调整顾问当作福音,它为你提供了为完成工作而生成的计划的建议,通常可以应用更好的索引。
如果有效地使表的大小加倍,则所有列上的非聚簇索引。因为您将拥有聚簇索引(实际表)和非聚簇索引中的副本。如果要插入表格,这将使写入量增加一倍。
如果您从一个表开始选择,但只是在索引键的where子句中有两列,那么Proposal_ID
和Is_Deleted
上的索引。使用SET STATISTICS IO ON
和执行计划,看看它在做什么然后你可以在那里玩。
Richie Rump的统计解析器:http://statisticsparser.com/用于读取统计信息的输出
答案 2 :(得分:1)
我错过了创建一些索引吗?这是因为糟糕的设计源于将大尺寸的nvarchar放在同一张桌子上?
在所有情况下,我都可以看到经过的时间不一致..但整体cpu时间保持相对较低..
如果我的查询以1毫秒开始并且需要8000毫秒,这是查询/经过时间的总时间,但在此CPU时间内只能是10毫秒..
这似乎发生在你的情况下,尝试运行查询,你会看到查询等待cpu ..
最后,我没有看到你的查询和索引的任何问题,我相信你看到的执行时间是由于等待统计数据