3

我有一个由列和索引组成的简单表,如下所示。

列

索引

这是我根据 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

每当我添加在图片 1 中检查的列时,执行时间都会严重增加。这是我的测试结果。

如果我不包括上述列。

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 行)表“PROPOSAL_PROCESS”。扫描计数 1,逻辑读取 58,物理读取 2,预读读取 55,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

(1 行受影响)

SQL Server 执行时间: CPU 时间 = 31 毫秒,经过时间 = 16 毫秒。 SQL Server 解析和编译时间: CPU 时间 = 0 毫秒,运行时间 = 0 毫秒。

SQL Server 执行时间:CPU 时间 = 0 毫秒,经过时间 = 0 毫秒。

如果我将 CURRENT_PROPOSAL_OBJECT 添加到先前查询的选择子句

(受影响的 54 行)表“PROPOSAL_PROCESS”。扫描计数 1,逻辑读取 58,物理读取 2,预读读取 55,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

(1 行受影响)

SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 545 毫秒。 SQL Server 解析和编译时间: CPU 时间 = 0 毫秒,运行时间 = 0 毫秒。

如果我将 INTERFACTORING_XML 添加到先前查询的选择子句

(受影响的 54 行)表“PROPOSAL_PROCESS”。扫描计数 1,逻辑读取 58,物理读取 2,预读读取 55,lob 逻辑读取 1822,lob 物理读取 376,lob 预读读取 0。

(1 行受影响)

SQL Server 执行时间: CPU 时间 = 47 毫秒,经过时间 = 2415 毫秒。 SQL Server 解析和编译时间: CPU 时间 = 0 毫秒,运行时间 = 0 毫秒。

如果我将 CURRENT_PROPOSAL_OBJECT 添加到先前查询的选择子句

(受影响的 54 行)表“PROPOSAL_PROCESS”。扫描计数 1,逻辑读取 58,物理读取 2,预读读取 55,lob 逻辑读取 5048,lob 物理读取 944,lob 预读读取 0。

(1 行受影响)

SQL Server 执行时间: CPU 时间 = 47 毫秒,经过时间 = 6912 毫秒。 SQL Server 解析和编译时间: CPU 时间 = 0 毫秒,运行时间 = 0 毫秒。

所以在一天结束时,我面临着 6912 英里的秒数。这种糟糕表现的原因是什么?

我想创建一些索引吗?这是由于将大尺寸的 nvarchar 放在同一张表中而导致设计不良的结果吗?

提前致谢

编辑:是重新生成问题的脚本。我试图在 sql-fiddle 上创建相同的问题,但它甚至没有插入一行。

编辑 2:如果我在 select 子句中包含所有列,并且只提供另一个提案 ID 使查询返回 2 行,则执行时间通常保持在 100 毫秒左右。查询执行时间会随着返回行的增加而变得越来越差。否与索引的联系。

4

3 回答 3

1

不要把调优顾问当成福音,它会给你建议它为完成工作而生成的计划,通常可以应用更好的索引。

如果有效地将表的大小加倍,则所有列上的非聚集索引。因为您将拥有聚集索引(实际表)和非聚集索引中的副本。如果您要插入表中,这将使写入量增加一倍。

如果您从一个表开始选择,但只有在您的索引键的 where 子句中有两列,那么在Proposal_IDand上的索引Is_Deleted。使用SET STATISTICS IO ON和执行计划,看看它在做什么,然后你可以从那里开始玩。

Richie Rump 的统计解析器:http ://statisticsparser.com/ 非常适合从统计 io 读取输出

于 2017-10-03T09:16:55.260 回答
1

我想创建一些索引吗?这是由于将大尺寸的 nvarchar 放在同一张表中而导致设计不良的结果吗?

在您的所有情况下,我都可以看到经过的时间不一致..但整体 cpu 时间保持相对较低..

如果我的查询从 1 毫秒开始并花费 8000 毫秒,这是查询的总时间/经过的时间,但在这个 CPU 时间只能是 10 毫秒。

这似乎发生在您的情况下,尝试运行查询,您将看到查询等待 cpu ..

最后,我没有看到您的查询和索引有任何问题,我相信您看到的执行时间是由于等待统计信息

于 2017-10-03T09:21:49.717 回答
1

NVARCHAR(max) 是旧的 ntext 数据类型的替代品。

ntext 将始终将其信息存储为行外的 BLOB。在可能的情况下,NVARCHAR(max) 将尝试将信息存储在行中。如果由于大小而不能,那么它将文本存储在 BLOB 中。

SQL Server 将处理从 BLOB 转换回可读的 nvarchar 文本,但不是免费的。每次 SQL Server 必须退出行,这是额外的开销。

调优顾问有效地告诉你这一点。将第一个查询 (0) 上的 lob(大对象)读取数与后面并引用 nvarchar(max) 字段的读取数进行比较。

于 2017-10-03T09:15:47.857 回答