【问题标题】:Optimization for Date Correlation doesn’t change plan日期相关性的优化不会改变计划
【发布时间】:2016-06-10 06:26:21
【问题描述】:

我有以下表格的报告要求。我用这些表创建了一个新数据库,并从实时数据库中导入了数据以用于报告目的。

报告参数是一个日期范围。我阅读了以下内容,发现DATE_CORRELATION_OPTIMIZATION 可用于通过使用查找而不是扫描来使查询更快地工作。我进行了必要的设置——查询仍然使用相同的旧计划和相同的执行时间。需要进行哪些额外更改才能使查询利用日期相关性?

注意:我使用的是 SQL Server 2005

参考文献

  1. Optimizing Queries That Access Correlated datetime Columns
  2. The Query Optimizer: Date Correlation Optimisation

SQL

--Database change made for date correlation
ALTER DATABASE BISourcingTest
   SET DATE_CORRELATION_OPTIMIZATION ON;
GO

--Settings made
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET ARITHABORT ON
SET CONCAT_NULL_YIELDS_NULL ON
SET QUOTED_IDENTIFIER ON
SET NUMERIC_ROUNDABORT OFF
GO

--Test Setting
IF (  (sessionproperty('ANSI_NULLS') = 1) AND
      (sessionproperty('ANSI_PADDING') = 1) AND 
      (sessionproperty('ANSI_WARNINGS') = 1) AND 
      (sessionproperty('ARITHABORT') = 1) AND 
      (sessionproperty('CONCAT_NULL_YIELDS_NULL') = 1) AND 
      (sessionproperty('QUOTED_IDENTIFIER') = 1) AND 
      (sessionproperty('NUMERIC_ROUNDABORT') = 0)  
    )
   PRINT 'Everything is set'
ELSE
   PRINT 'Different Setting'

--Query
SELECT C.ContainerID, C.CreatedOnDate,OLIC.OrderID
FROM ContainersTest C
INNER JOIN OrderLineItemContainers OLIC
    ON OLIC.ContainerID = C.ContainerID
WHERE C.CreatedOnDate > '1/1/2015'
AND C.CreatedOnDate < '2/01/2015'

表格

CREATE TABLE [dbo].[ContainersTest](
    [ContainerID] [varchar](20) NOT NULL,
    [Weight] [decimal](9, 2) NOT NULL DEFAULT ((0)),
    [CreatedOnDate] [datetime] NOT NULL DEFAULT (getdate()),
 CONSTRAINT [XPKContainersTest] PRIMARY KEY CLUSTERED 
(
    [CreatedOnDate] ASC,
    [ContainerID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[OrderLineItemContainers](
    [OrderID] [int] NOT NULL,
    [LineItemID] [int] NOT NULL,
    [ContainerID] [varchar](20) NOT NULL,
    [CreatedOnDate] [datetime] NOT NULL DEFAULT (getdate()),
 CONSTRAINT [PK_POLineItemContainers] PRIMARY KEY CLUSTERED 
(
    [OrderID] ASC,
    [LineItemID] ASC,
    [ContainerID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
 CONSTRAINT [IX_OrderLineItemContainers] UNIQUE NONCLUSTERED 
(
    [ContainerID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[OrderLineItemContainers]  WITH CHECK ADD  CONSTRAINT [FK_POLineItemContainers_Containers] FOREIGN KEY([ContainerID])
REFERENCES [dbo].[Containers] ([ContainerID])
GO
ALTER TABLE [dbo].[OrderLineItemContainers] CHECK CONSTRAINT [FK_POLineItemContainers_Containers]

计划

--

【问题讨论】:

  • 您是否尝试过删除当前查询计划并重新运行以创建一个新计划?
  • 我在测试数据库 (SS2012) 上创建了您的表。桌子当然是空的;我得到两个索引搜索 + 用于内部连接的嵌套循环。可能是您的 SQL Server 实例上的优化器认为执行搜索 + 扫描和内部连接的哈希匹配更快。另外,帮自己一个忙,使用YYYYMMDD 作为日期格式。
  • 创建表并导入数据后,表索引可能会碎片化,表统计信息可能会过时或在自动更新后不具有代表性。尝试对参与查询的两个表执行alter index all on [tableName] rebuild 加上update statistics [tableName] with fullscan。然后重新测试您的查询。
  • @StevenHibble 那DATE_CORRELATION_OPTIMIZATION有什么用呢?
  • @Lijo 也许你可以看看the internal view that is created?也许 SQL Server 很难找到相关性。

标签: sql-server optimization sql-server-2005


【解决方案1】:

根据文档: https://technet.microsoft.com/en-us/library/ms177416(v=sql.105).aspx

如果维护相关统计信息的日期时间列中的任何一个不是聚集索引的第一个键或唯一键,请考虑在其上创建聚集索引。这样做通常会在相关统计信息涵盖的查询类型上获得更好的性能。如果主键列上已经存在聚集索引,您可以修改表,使聚集索引和主键使用不同的列集。

由于您的 OrderLineItemContainers 表没有合适的索引来过滤日期,因此它真的无能为力。尝试在 OrderLineItemContainers.CreatedOnDate 上添加一个非聚集索引,看看它是否会切换计划。

最好将其聚集在一起,但还有其他注意事项...请注意,您可以将主键设为非聚集,如果这是主要查询,则将聚集用于此新日期索引,这值得它。

所以这是最优的:

CREATE TABLE [dbo].[OrderLineItemContainers](
      [OrderID] [int] NOT NULL,
      [LineItemID] [int] NOT NULL,
      [ContainerID] [varchar](20) NOT NULL,
      [CreatedOnDate] [datetime] NOT NULL DEFAULT (getdate()),
   CONSTRAINT [PK_POLineItemContainers] PRIMARY KEY NONCLUSTERED -- NONCLUSTERED PRIMARY KEY!!
        (
            [OrderID] ASC,
            [LineItemID] ASC,
            [ContainerID] ASC
        )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
         CONSTRAINT [IX_OrderLineItemContainers] UNIQUE NONCLUSTERED 
        (
            [ContainerID] ASC
        )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
        ) ON [PRIMARY]

CREATE CLUSTERED INDEX ON OrderLineItemContainers(CreatedOnDate)

或者你可以尝试一个新的非集群索引:

CREATE NONCLUSTERED INDEX ON OrderLineItemContainers(CreatedOnDate)

【讨论】:

  • 请注意“您不应在更新密集型数据库环境中启用 DATE_CORRELATION_OPTIMIZATION”。如果是这种情况,您可能希望采用其他优化策略...例如先将 ContainersTest 表中的候选行拉入临时表,然后再进行第二次连接。
  • 感谢您的回复。但是即使添加了非聚集索引,它也没有改变执行计划和时间
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-29
  • 2016-11-06
  • 1970-01-01
相关资源
最近更新 更多