我最近更改了表上的索引,发现一个查询的性能损失很大。我想知道为什么会发生这种情况。
这就是查询。外键就像
From
和
To
正在发生变化,但其余的会保持不变,并经常重复。
SELECT COUNT(*)
FROM Table_With_Values
WHERE FK_ObjectTheValuesBelongTo_Id = 460
AND [From]>=CONVERT([datetime2](3),'07.10.2024 00:00:00',(104))
AND [To]<=CONVERT([datetime2](3),'08.10.2024 00:00:00',(104))
首先是表的索引
TableWithValues
看起来像这样:
CREATE NONCLUSTERED INDEX [Idx_TableWithValues_Fk_ObjectTheValuesBelongTo_Id_From_To] ON [dbo].[TableWithValues]
(
[Fk_ObjectTheValuesBelongTo_Id] ASC,
[From] ASC,
[To] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
然后我读了
SQL Server documentation
并看到了这一点:
如果索引包含多个列,请考虑列的顺序
柱。在WHERE子句中使用的列等于
(=)、大于(>)、小于(<)或在搜索条件之间,或
参加加盟,应该放在第一位。
其他栏目
应根据其清晰度进行排序,即从
从最明显到最不明显
.
这个
从
和
致
列有大约140000个不同的值,而外键列只有1600个。因此,我决定改变它们的顺序,使索引看起来像这样:
CREATE NONCLUSTERED INDEX [Idx_TableWithValues_From_To_Fk_ObjectTheValuesBelongTo_Id] ON [dbo].[TableWithValues]
(
[From] ASC,
[To] ASC,
[Fk_ObjectTheValuesBelongTo_Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
然而,这导致了此查询的性能下降。执行需要1000倍的时间。我知道这一点,因为我在数据库的副本上激活了查询存储。然后,我运行了发送查询的IT系统,并检查了中的值
avg_duration
桌子的
query_store_runtime_stats
.
表格本身看起来像这样:
CREATE TABLE [dbo].[TableWithValues](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Fk_ObjectTheValuesBelongTo_Id] [int] NOT NULL,
[Value] [decimal](9, 3) NOT NULL,
[From] [smalldatetime] NOT NULL,
[To] [smalldatetime] NOT NULL,
CONSTRAINT [Pk_TableWithValues_Id] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [Uq_TableWithValues_ObjectTheValuesBelongTo_Id_From] UNIQUE NONCLUSTERED
(
[Fk_ObjectTheValuesBelongTo_Id] ASC,
[From] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[TableWithValues] WITH CHECK ADD CONSTRAINT [Fk_TableWithValues_ObjectTheValuesBelongTo_Id] FOREIGN KEY([Fk_ObjectTheValuesBelongTo_Id])
REFERENCES [dbo].[ObjectTheValuesBelongTo] ([Id])
GO
具有这两个索引的运行的查询计划看起来几乎相同。有两个不同之处。他们使用不同的索引(隐藏在屏幕截图中),在一种情况下,百分比为13%和87%(Fk在索引中排名第一),在另一种情况中,百分比为20%和80%(Fk排在索引的最后)。
知道吗,为什么我的数据库在阅读文档时表现得不像人们预期的那样?