如何提高选择速度?

Man*_*oon 4 performance sql-server query-performance

我有一个这样设置的表:

DB 有 10B 行。

CREATE TABLE [Tick].[X_H](
       [utcDT] [datetime2](7) NOT NULL,
       [Symbol] [nvarchar](50) NOT NULL,
       [Bid] [float] NULL,
       [Ask] [float] NULL,
       [BidSize] [float] NULL,
       [AskSize] [float] NULL
) ON [PRIMARY] 


ALTER TABLE [Tick].[X_H] ADD  CONSTRAINT [PK_Master] PRIMARY KEY CLUSTERED 
(
       [utcDT] ASC,
       [Symbol] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = ON, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
Run Code Online (Sandbox Code Playgroud)

我想为特定符号选择一天的数据。我在用:

SELECT *  
FROM [Tick].[X_H] 
WHERE [Symbol] = 'DONKEY' 
AND CONVERT(Date, [utcDT]) = CONVERT(Date,'2011-01-02');
Run Code Online (Sandbox Code Playgroud)

这比从二进制文件读取相同的数据并反序列化它需要 3 倍的时间。二进制读取为 42 毫秒,SQL 读取为 115 毫秒。

我可以尝试什么来加速它?


建议创建一个单独的 [Date] 列,我已经添加了 2 个索引。

ALTER TABLE [Tick].[FX_HS] ADD [Date] DATE NULL;
UPDATE [Tick].[X_H] SET [Date] = CONVERT(Date,[utcDT])
CREATE INDEX I_Date ON [Tick].[X_H] ([Date]); 
CREATE INDEX I_SymbolDate ON [Tick].[X_H] ([Symbol],[Date]);
Run Code Online (Sandbox Code Playgroud)

我正在使用查询:

SELECT *  FROM [Tick].[X_H] WHERE [Symbol] = 'DONKEY' AND [Date] = '2011-01-02';
Run Code Online (Sandbox Code Playgroud)

但这需要大约相同的时间!


执行计划

粘贴计划

Query 1: Query cost(relative to batch): 100%
SELECT * FROM [Tick][X_H] WHERE [Symbol]=@1 AND [Date]=@2
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


正如马丁·史密斯所建议的:

SET STATISTICS TIME ON

DECLARE @utcDT DATETIME2(7)
DECLARE @Symbol NVARCHAR(50)
DECLARE @Bid FLOAT
DECLARE @Ask FLOAT
DECLARE @BidSize FLOAT
DECLARE @AskSize FLOAT
DECLARE @Date DATE

SELECT @utcDT = utcDT,
       @Symbol = Symbol,
       @Bid = Bid,
       @Ask = Ask,
       @BidSize = BidSize,
       @AskSize = AskSize,
       @Date = Date
FROM   Tick.X_H
WHERE  ( Symbol = 'DONKEY' )
       AND ( Date = '2011-01-02' )
Run Code Online (Sandbox Code Playgroud)

这需要:

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

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

Sql*_*Zim 8

你的where条件是平等检查utcdt转换为日期是优化搜索,但使用的是动态的寻求

问题是这些隐藏的隐式转换可能导致计划的任何阶段的基数和分布估计不准确。因此,即使您进行了搜索,该计划也可能与总体上相差甚远。-动态搜索和隐藏的隐式转换 - Paul White

尝试将您的where条件转换为明确的范围,看看是否有任何改进:

select *
from Tick.X_H
where Symbol = 'donkey'
  and utcdt >= convert(datetime2(7),'20110102')
  and utcdt <  convert(datetime2(7),'20110103')
Run Code Online (Sandbox Code Playgroud)

根据Martin Smith这个答案,显式范围可能会减少不必要的读取。

参考: