优化建议的可疑重复索引

Zap*_*ica 6 index sql-server index-tuning azure-sql-database

美好的一天,我有以下 sql server 数据库表: 在此处输入图片说明

请注意复合主键。这样做有 3 个原因:

  • 防止重复输入
  • 提高查询性能,因为所有查询都将具有所有 3 个键。
  • 我们需要和索引,我不想引入随机 ID。

另请注意,此表的设计考虑了其大小,此表将存储数百万行数据。

好的,现在我的实际问题。我正在使用 azure sql server 来托管这个数据库。我启用了自动调整。奇怪的是,我看到它然后创建了一个新索引。(见下文)

在此处输入图片说明

现在在我看来,这似乎是一个重复的索引,因为正在索引相同的列。

所以我的桌子上现在有两个索引:

原版(我的PK):

ALTER TABLE [dbo].[SensorDataRaw] ADD  CONSTRAINT [PK_SensorDataRaw] PRIMARY KEY CLUSTERED 
(
    [DateTime] ASC,
    [SensorId] ASC,
    [Key] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
Run Code Online (Sandbox Code Playgroud)

新增(由天蓝色调校自动创建):

CREATE NONCLUSTERED INDEX [nci_wi_SensorDataRaw_DC9789077DA75B4440AC8BFE3E2AA198] ON [dbo].[SensorDataRaw]
(
    [Key] ASC,
    [SensorId] ASC,
    [DateTime] ASC
)
INCLUDE (   [Value]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
Run Code Online (Sandbox Code Playgroud)

观察:

  • 新索引中列的顺序已颠倒。
  • 新索引不是唯一的
  • 新索引包括值列。

请注意,我对索引的了解并不先进,因此我提出了这个问题。

所以我的问题是:

  1. 有人可以解释为什么新添加的索引比我最初创建的更好。
  2. 如何删除两个索引并创建一个涵盖这两种情况的索引。由于这是一个如此庞大的数据库,我无法承受这两个索引将占用的空间。
  3. 也许是更好的设计选择?

附加信息:

我假设查询的类型在这里变得很重要,所以我列出了一些例子。

所有查询包括DateTimeSensorId,和Key

简单查询:

Select SensorId Where average value for key w is greater than x where time between (y,z)
Run Code Online (Sandbox Code Playgroud)

绘图数据:

SELECT AVG([Value]) AS 'AvgValue',    
    DATEADD( MINUTE, 
    (DATEDIFF(MINUTE, '1990-01-01T00:00:00', [dbo].[SensorDataRaw].
[DateTime]) / @IntervalInMinutes) * @IntervalInMinutes,
        '1990-01-01T00:00:00'
    )      AS 'TimeGroup'
 FROM [dbo].[SensorDataRaw]
 where 
    [dbo].[SensorDataRaw].[SensorId] = @SensorId
    and [dbo].[SensorDataRaw].[Key] = @KeyValue
    and [dbo].[SensorDataRaw].[DateTime] Between @DateFrom and @DateTo
    and [dbo].[SensorDataRaw].[Value] IS NOT NULL  
  GROUP BY (DATEDIFF(MINUTE, '1990-01-01T00:00:00', [dbo].[SensorDataRaw].
    [DateTime]) / @IntervalInMinutes)
Run Code Online (Sandbox Code Playgroud)

Mar*_*ith 6

系统建议的索引更适合您显示的查询。您应该将具有相等谓词的列作为前导列。

考虑由 订购的电话簿lastname, firstname。如果您的要求是查找所有姓氏介于“Brown”和“Yates”之间且名字为“John”的人,那么您需要阅读大部分电话簿。如果电话簿是由firstname, lastname您订购的,您可以轻松找到“John”部分和该部分中的第一个“Brown”,那么您需要做的就是阅读所有姓名,直到lastname在“Yates”之后或遇到新的名字。

它可能不是理想的索引。可能您应该只将聚集索引中的键列更改为此顺序,而不是创建一个新的列。您需要根据对工作负载的了解对此进行评估。

  • 只要每个 (key,sensor) 对有数千行,为每个 (key,sensor) 设置一个单独的插入点就不会导致错误的碎片化。参见,例如 https://blogs.msdn.microsoft.com/dbrowne/2012/06/25/good-page-splits-and-sequential-guid-key-generation/ (3认同)
  • 那么你所阅读的内容是不完整的。一旦你阅读了我的答案,你就会读到不同的东西。列顺序只有在它们都在等式谓词中时才无关紧要。 (2认同)
  • @sepupic - 是的,他们可以保留 PK 但只是重新排序列 - 这不会影响唯一性方面。但正如我所说,OP 需要根据他们的整个工作量(包括插入)来评估这一点 (2认同)