我有一个带有重复查询的 SQL Server 表,我需要提高其性能。我需要检索与下面的 where 子句匹配的记录。所有 3 列都是 datetime2 列。
WHERE GREATEST(dateColumn1, dateColumn2) > dateColumn3
为表建立索引以提高性能的最佳方法是什么?
我应该创建一个计算列并为其建立索引吗?
为表建立索引以提高性能的最佳方法是什么?
将您的
WHERE
谓词子句表达式放入计算列中,然后对该列建立索引。
上次我检查时,SQL Server(包括 Azure SQL)不支持在
CREATE INDEX
语句中使用任意表达式,因此您想要索引的任何表达式都必须定义为计算(但不一定是 PERSISTED
)列 .
...几个月前我自己就这样做了,但我遇到了一个😩诱发错误:如果你在SQL Server 2022 或 Azure SQL 中的计算列表达式。 因为您需要定义一个将按原样索引的计算列,然后考虑您可以...
将计算列简单地定义为
PERSISTED
的结果 - 这意味着您仍然需要在
LEAST
查询中进行 GREATEST
比较,并且如果您的查询发生哪怕最轻微的变化,也可能会遇到糟糕的查询计划选择。数据库。
GREATEST( col1, col2, etc )
另一个计算列,并在其上定义
>
;您需要更新您的 SELECT
查询以直接引用新的计算列,但这会显着降低 SQL Server 生成错误查询计划的几率(但 YMMV、ofc)。>
和
INDEX
列都是
SELECT
。(如果它们实际上是
dateCol1
dateCol2
或
datetime2(7) NOT NULL
式谓词)无论如何,像这样:NULL
请注意,我定义了 dateCol1 IS NOT NULL
和
dateCol1 IS NOT DISTINCT FROM dateCol2
- 以及关联的 -- Before doing anything, ensure we're in a standards-compliant environment, which is important for PERSISTED columns:
SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON
SET XACT_ABORT ON;
BEGIN TRANSACTION ddlTxn;
RAISERROR( 'Now running ALTER TABLE...', 0, 1) WITH NOWAIT;
ALTER TABLE dbo.MyTable
ADD
Greatest_1_or_2 AS GREATEST( dateCol1, dateCol2 ) PERSISTED NOT NULL,
DateCol_1_or_2_is_gt_3 AS ( CASE WHEN GREATEST( dateCol1, dateCol2 ) > dateCol3 THEN CONVERT(bit,1) ELSE CONVERT(bit,0) END ) PERSISTED NOT NULL,
DateCol_1_or_2_diff_3 AS ( DATEDIFF( microsecond, GREATEST( dateCol1, dateCol2 ) - dateCol3 ) PERSISTED NOT NULL;
RAISERROR( 'Now running CREATE INDEX...', 0, 1) WITH NOWAIT;
CREATE INDEX IX_Greatest12 ON dbo.MyTable ( Greatest_1_or_2 ) INCLUDE ( dateCol3 );
CREATE INDEX IX_Greatest12IsGT3 ON dbo.MyTable ( DateCol_1_or_2_is_gt_3 );
CREATE INDEX IX_DateCol12Diff3 ON dbo.MyTable ( DateCol_1_or_2_diff_3 );
COMMIT TRANSACTION ddlTxn;
索引 - 因此您可能希望根据实际查询选择一组或另一组(或两者?)。
因此您的查询现在可能如下所示:
DateCol_1_or_2_is_gt_3
DateCol_1_or_2_diff_3
或:
IX_
在互联网上
,我什么也看不见:)