基于这些问题和给出的答案:
SQL 2008 Server - 性能损失可能与非常大的表有关
具有历史数据的大型表分配了过多的 SQL Server 2008 Std。内存 - 其他数据库的性能损失
我在数据库 SupervisionP 中有一个表,定义如下:
CREATE TABLE [dbo].[PenData](
[IDUkazatel] [smallint] NOT NULL,
[Cas] [datetime2](0) NOT NULL,
[Hodnota] [real] NULL,
[HodnotaMax] [real] NULL,
[HodnotaMin] [real] NULL,
CONSTRAINT [PK_Data] PRIMARY KEY CLUSTERED
(
[IDUkazatel] ASC,
[Cas] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[PenData] WITH NOCHECK ADD CONSTRAINT [FK_Data_Ukazatel] FOREIGN KEY([IDUkazatel])
REFERENCES [dbo].[Ukazatel] ([IDUkazatel])
ALTER TABLE [dbo].[PenData] CHECK CONSTRAINT [FK_Data_Ukazatel]
它包含 cca 2.11 亿行。
我运行以下语句:
DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;
SET @t1 = GETDATE();
SELECT min(cas) from PenData p WHERE IDUkazatel=24
SELECT min(cas) from PenData p WHERE IDUkazatel=25
SET @t2 = GETDATE();
SELECT DATEDIFF(millisecond,@t1,@t2) AS elapsed_ms;
SET @t1 = GETDATE();
SELECT min(cas) from PenData p WHERE IDUkazatel=24 OR IDUkazatel=25
SET @t2 = GETDATE();
SELECT DATEDIFF(millisecond,@t1,@t2) AS elapsed_ms;
结果显示在这里:
第三个 SELECT 还将更多数据加载到 SQL Server 内存缓存中。
为什么第三个 SELECT 比前两个 SELECT(16 毫秒)慢得多(8.5 秒)?如何使用 OR 提高第三个选择的性能?我想运行以下 SQL 命令,但在我看来,在这种情况下,创建游标和运行单独的查询比单个选择要快得多。
SELECT MIN(cas) from PenData p WHERE IDUkazatel IN (SELECT IDUkazatel FROM ...)
编辑
正如大卫建议的那样,我将鼠标悬停在粗箭头上:
对于前两个查询,它所要做的就是在聚集索引中扫描该值的第一个条目
IDUkazatel
- 因为索引的顺序,该行将是该值的 cas 的最低值IDUkazatel
。在第二个查询中,此优化不是价值,它可能正在寻找第一行,
IDUkazatel=24
然后向下扫描索引直到最后一行,以找到所有这些行IDUkazatel=25
的最小值。cas
如果您将鼠标悬停在那个粗箭头上,您会看到它正在读取许多行(当然是所有 24 行,也可能是所有 25 行),而其他两个的计划输出中的细箭头显示
top
导致它仅考虑一行。您可以尝试运行每个查询,然后获取找到的最小值的最小值:
也就是说,您似乎有一个包含
IDUkazatel
值而不是显式OR
子句的表。下面的代码将使用这种安排,只需将表名替换为@T
包含IDUkazatel
值的表名:在理想情况下,SQL Server 查询优化器会为您执行此重写,但现在并不总是考虑此选项。