在行ID上输入“聚集的身份”主键时,按添加日期进行排序和过滤

时间:2018-10-02 11:40:43

标签: sql-server sql-order-by clustered-index

我有一个表格(OrdersCLUSTERED IDENTITY PRIMARY KEYOrderId),并且我正在过滤排序添加日期列(AddDate)。 有没有一种方法可以告诉查询优化器AddDate的排序方式与OrderId相同(因此数据已经由AddDate排序了)?

SQL Server确实不需要扫描整个表然后对其进行排序。所有操作所需的是扫描表直到找到结束日期,然后在开始日期之前过滤掉数据并按原样返回(不进行排序)。

示例:

SELECT
      *
    FROM Orders
    WHERE AddDate BETWEEN @FromDate AND @ToDate
    ORDER BY AddDate

3 个答案:

答案 0 :(得分:4)

  

有没有办法告诉查询优化器AddDate是有序的   OrderId的方式相同(因此,数据由AddDate排序   已经)?

不,没有任何办法。

但是,您可以通过interface Bar<T extends NoParameterCtor<unknown>> { theConstructor: T, theInstance: InstanceType<T> } class Zar implements Bar<typeof Zoo> { theConstructor = Zoo; // the constructor theInstance = new Zoo(); // an instance } 而不是OrderId进行订购,如果AddDate的订购方式与AddDate相同,则会返回相同的结果。但是不幸的是,SQL Server还是会扫描整个表。

不要使用Northwind订单表和OrderDate列。

查询:

OrderId

产生this plan。在应用过滤器时,它将完全扫描聚簇索引,然后对结果进行排序。

查询:

SELECT *
FROM dbo.Orders
WHERE OrderDate BETWEEN '1997-12-10' AND '1998-03-05'
ORDER BY OrderDate

产生this plan。它还会完全扫描聚簇索引并应用过滤器,但是不排序。

使用SELECT * FROM dbo.Orders WHERE OrderDate BETWEEN '1997-12-10' AND '1997-12-17' ORDER BY OrderId -- It's equivalent to ordering by OrderDate 作为聚簇索引键将大大提高查询的性能,但是您可能不希望拥有这样的聚簇索引键。但是,您通过云创建覆盖索引,该索引也将大大提高性能:

OrderDate

查询:

CREATE INDEX IX_Orders_OrderDate ON dbo.Orders(OrderDate)
INCLUDE ([OrderID], [CustomerID], [EmployeeID], [RequiredDate], [ShippedDate], [ShipVia], [Freight], [ShipName], [ShipAddress], [ShipCity], [ShipRegion], [ShipPostalCode], [ShipCountry])

产生this plan。它只是在寻找索引。它不可能更快。

但是该索引很胖,它会惩罚数据修改。

但是,您可以利用以下更薄的索引:

SELECT *
FROM dbo.Orders
WHERE OrderDate BETWEEN '1997-12-10' AND '1998-03-05'
ORDER BY OrderDate

使用这样的查询:

CREATE INDEX IX_Orders_OrderDate ON dbo.Orders(OrderDate, OrderId)

它产生this plan。只需3次即可解决查询。

答案 1 :(得分:2)

您无能为力了。首先,如果您知道排序方式相同,则没有理由为什么要用AddDate而不是OrderId来排序结果集。 其次,如果您知道这种关系,您可以按照@耶稣向您展示的日期框架OrderId进行分配。 最好的方法是在OrderDate(仅)上创建附加索引。对于这样一个简单的查询,这将是最好的方法,不需要包括额外的列,无论如何,PK都将在后台覆盖,并且将基于整个过滤。 您仍然可以带来一些改进的最后一个选择(虽然不如索引好,但仍会有所帮助)是在OrderDate列上添加额外的统计信息,基于这些统计信息,SQL Server的kardionality估计器将能够产生这些统计信息更好的计划应该可以提高性能。

答案 2 :(得分:1)

您可以在AddDate的OrderId上添加非聚集索引:

CREATE INDEX IX_Orders_AddDate_OrderID
ON dbo.Orders(AddDate, OrderID)

然后重写查询:

SELECT       *
FROM Orders
WHERE OrderId >=
           (SELECT MIN(OrderId)
            FROM dbo.Orders
            WHERE AddDate >= @FromDate) AND
      OrderId <=
           (SELECT MAX(OrderId)
            FROM dbo.Orders
            WHERE AddDate <= @ToDate)
ORDER BY AddDate