sql - 当我使用我为它创建的索引时,为什么我的查询会变慢?

标签 sql sql-server azure-sql-database

我有下表,用 EntityFramework 6.1 制作:

CREATE TABLE [dbo].[MachineryReading] (
    [Id]                 INT              IDENTITY (1, 1) NOT NULL,
    [Location]           [sys].[geometry] NULL,
    [Latitude]           FLOAT (53)       NOT NULL,
    [Longitude]          FLOAT (53)       NOT NULL,
    [Altitude]           FLOAT (53)       NULL,
    [Odometer]           INT              NULL,
    [Speed]              FLOAT (53)       NULL,
    [BatteryLevel]       INT              NULL,
    [PinFlags]           BIGINT           NOT NULL,
    [DateRecorded]       DATETIME         NOT NULL,
    [DateReceived]       DATETIME         NOT NULL,
    [Satellites]         INT              NOT NULL,
    [HDOP]               FLOAT (53)       NOT NULL,
    [MachineryId]        INT              NOT NULL,
    [TrackerId]          INT              NOT NULL,
    [ReportType]         NVARCHAR (1)     NULL,
    [FixStatus]          INT              DEFAULT ((0)) NOT NULL,
    [AlarmStatus]        INT              DEFAULT ((0)) NOT NULL,
    [OperationalSeconds] INT              DEFAULT ((0)) NOT NULL,
    CONSTRAINT [PK_dbo.MachineryReading] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.MachineryReading_dbo.Machinery_MachineryId] FOREIGN KEY ([MachineryId]) REFERENCES [dbo].[Machinery] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_dbo.MachineryReading_dbo.Tracker_TrackerId] FOREIGN KEY ([TrackerId]) REFERENCES [dbo].[Tracker] ([Id]) ON DELETE CASCADE
);

GO
CREATE NONCLUSTERED INDEX [IX_MachineryId]
    ON [dbo].[MachineryReading]([MachineryId] ASC);


GO
CREATE NONCLUSTERED INDEX [IX_TrackerId]
    ON [dbo].[MachineryReading]([TrackerId] ASC);

这是很多信息,我们最常见(也是最慢)的查询只使用其中的一个子集:
SELECT TOP 1 OperationalSeconds
  FROM MachineryReading
  WHERE MachineryId = @id
    AND DateRecorded > @start
    AND DateRecorded < @end
    AND OperationalSeconds <> 0

该表存储了几百万行,大约从 2012 年开始记录,尽管我们的代码设置为从 2000 年开始进行一些搜索。它运行得非常缓慢,所以与我合作的一个人根据 DateRecorded 对表进行了分区:
ALTER PARTITION SCHEME PartitionSchemeMonthRange NEXT USED [Primary]
ALTER PARTITION FUNCTION [PartitionFunctionMonthRange]() SPLIT RANGE(N'2016-01-01T00:00:00.000') 

ALTER PARTITION SCHEME PartitionSchemeMonthRange NEXT USED [Primary]
ALTER PARTITION FUNCTION [PartitionFunctionMonthRange]() SPLIT RANGE(N'2016-02-01T00:00:00.000') 
...

CREATE UNIQUE CLUSTERED INDEX [PK_dbo.MachineryReadingPs] ON MachineryReading(DateRecorded, Id) ON PartitionSchemeMonthRange(DateRecorded)

但是,上面的查询仍然运行得很慢。所以最重要的是,我制作了另一个索引:
CREATE NONCLUSTERED INDEX [IX_MachineryId_DateRecorded]
    ON [dbo].[MachineryReading]([DateRecorded] ASC, [MachineryId] ASC)
    INCLUDE([OperationalSeconds], [FixStatus]);

再次执行该查询,执行计划显示它完全忽略了我刚刚创建的索引,而是选择了对 IX_MachineryId 的常量扫描和索引查找。这对于小日期范围非常有效,但对于获得总运行时间来说很糟糕。

好的,我可以处理:WITH(INDEX(IX_MachineryId_DateRecorded)) .

不。当使用我专门为该查询创建的索引时,它实际上运行速度要慢得多!是什么赋予了?我可以做什么更好?

最佳答案

您在索引中的 MachineryId 之前有 DateRecorded。反转这些以获得更有效的索引。

关于sql - 当我使用我为它创建的索引时,为什么我的查询会变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41156146/

相关文章:

c# - 在 UWP 中连接到数据库时无法加载文件或程序集

Azure SQL 数据库错误 TLS 握手自 v12 升级以来失败

sql - 使用 'yyyymmdd' 格式将 Varchar 转换为 Datetime

php - MYSQL 最大/计数/输入/日期

sql - 使用 SQL 身份验证执行 SSIS 包

php - 如何使用连接编写mysql查询并在删除一个表中的记录时仍然显示部分信息?

azure - 如何在 AZURE EASY API 中编写选择函数

sql - 如何从oracle sql中只选择1行?

sql - 在存储过程中立即执行始终给出权限不足的错误

sql - 您可以使用 Sql PIVOT 查询在两列上进行透视和聚合吗