SQL 查询优化:从非聚集索引中获取额外的列数据
SQL query optimization: get extra column data from non-clustered index
我正在尝试对每天接收数百万条记录的 table 编写查询。我可以将我的查询缩小到一个时间片 (logdate
),但我需要它的额外列数据 (num
)。这是我用来测试它的示例查询:
DECLARE @StartTimeStamp DATETIME = '12/6/2019 7:56:50.799'
DECLARE @EndTimeStamp DATETIME = '12/6/2019 7:56:50.8'
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT tx.num, tx.logdate
FROM hsi.transactionxlog tx
WHERE tx.logdate BETWEEN @StartTimeStamp AND @EndTimeStamp
这个时间跨度为 0.001 秒的特定测试需要四分钟才能完成 运行。如果我将其更改为在指定时间范围内没有找到记录的时间范围,那么 运行 几乎需要一秒钟,即使指定 24 小时的跨度。
这个table只有非聚集索引。其中一个索引包含以下列:(num
、logdate
和 action
,顺序为)。
如何快速找到@StartTimeStamp和@EndTimeStamp之间每条记录对应的num
?我强烈不希望在此 table 上创建额外的索引,因为许多其他应用程序经常使用它。
对于这个查询:
select tx.num, tx.logdate
from hsi.transactionxlog tx
where tx.logdate BETWEEN @StartTimeStamp AND @EndTimeStamp;
最优指标为:transactionxlog(logdate, num)
。 logdate
应该是索引中的第一个键,因此它用于 where
条件。
我找到了临时 table 解决方案。这是解决方案的实质:
DECLARE @StartTimeStamp DATETIME = '12/6/2019 7:56:50.799'
DECLARE @EndTimeStamp DATETIME = '12/6/2019 7:56:50.8'
DECLARE @TempTable TABLE (logdate DATETIME, action BIGINT)
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
INSERT INTO @TempTable
SELECT logdate, action FROM hsi.transactionxlog
WHERE logdate BETWEEN @StartTimeStamp AND @EndTimeStamp
SELECT tx.num, tx.logdate
FROM hsi.transactionxlog tx
INNER JOIN @TempTable t ON t.logdate = tx.logdate AND t.action = tx.action
WHERE tx.logdate BETWEEN @StartTimeStamp AND @EndTimeStamp
我真的没有很好的解释为什么这有效,但它要快得多,并且时间尺度与 @StartTimeStamp
和 @EndTimeStamp
之间的时差适当。它只是选择几千条记录,然后出于某种原因 SQL 更容易在大 table.
中找到它们
感谢您查看问题并尝试回答。
我正在尝试对每天接收数百万条记录的 table 编写查询。我可以将我的查询缩小到一个时间片 (logdate
),但我需要它的额外列数据 (num
)。这是我用来测试它的示例查询:
DECLARE @StartTimeStamp DATETIME = '12/6/2019 7:56:50.799'
DECLARE @EndTimeStamp DATETIME = '12/6/2019 7:56:50.8'
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT tx.num, tx.logdate
FROM hsi.transactionxlog tx
WHERE tx.logdate BETWEEN @StartTimeStamp AND @EndTimeStamp
这个时间跨度为 0.001 秒的特定测试需要四分钟才能完成 运行。如果我将其更改为在指定时间范围内没有找到记录的时间范围,那么 运行 几乎需要一秒钟,即使指定 24 小时的跨度。
这个table只有非聚集索引。其中一个索引包含以下列:(num
、logdate
和 action
,顺序为)。
如何快速找到@StartTimeStamp和@EndTimeStamp之间每条记录对应的num
?我强烈不希望在此 table 上创建额外的索引,因为许多其他应用程序经常使用它。
对于这个查询:
select tx.num, tx.logdate
from hsi.transactionxlog tx
where tx.logdate BETWEEN @StartTimeStamp AND @EndTimeStamp;
最优指标为:transactionxlog(logdate, num)
。 logdate
应该是索引中的第一个键,因此它用于 where
条件。
我找到了临时 table 解决方案。这是解决方案的实质:
DECLARE @StartTimeStamp DATETIME = '12/6/2019 7:56:50.799'
DECLARE @EndTimeStamp DATETIME = '12/6/2019 7:56:50.8'
DECLARE @TempTable TABLE (logdate DATETIME, action BIGINT)
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
INSERT INTO @TempTable
SELECT logdate, action FROM hsi.transactionxlog
WHERE logdate BETWEEN @StartTimeStamp AND @EndTimeStamp
SELECT tx.num, tx.logdate
FROM hsi.transactionxlog tx
INNER JOIN @TempTable t ON t.logdate = tx.logdate AND t.action = tx.action
WHERE tx.logdate BETWEEN @StartTimeStamp AND @EndTimeStamp
我真的没有很好的解释为什么这有效,但它要快得多,并且时间尺度与 @StartTimeStamp
和 @EndTimeStamp
之间的时差适当。它只是选择几千条记录,然后出于某种原因 SQL 更容易在大 table.
感谢您查看问题并尝试回答。