SQL Server - 从连接表中选择最大/最小项目的最快方法

时间:2017-07-13 20:14:15

标签: sql-server tsql query-optimization

假设情况。

根据评论的要求添加有关数据集的更多详细信息:

  1. 表格订单:< 10万行。
  2. 表Orders_Log< 200毫升(v。粗略近似)。

  3. 大多数应用程序会将Orders表中的订单行限制为50k - 1 mln,其中80%的查询位于< 100K。 - > WHERE表上的{FROM子句将根据类型Category的顺序的VARCHAR将行数限制为100k。

  4. 指定方案的索引:CategoryOrderId

  5. OderId的类型为VARCHAR

  6. 表“订单”包含已完成的订单历史记录。

    | OrderID | Customer | NoOfItems | Category
    

    表“Orders_log”是一个日志表,用于存储与操作发生时的顺序和时间相关的操作。订单ID加入了它。这是1 .. *关系。

    | RowId | OrderId | Action | DateTime
    

    我正在寻找一种最快的方式加入与特定行动相匹配的第一个条目(按时间顺序排列),例如:'项目已添加到购物车'

    我的建议:

    SELECT
        [OrderId]
    ,   [Action]
    ,   [NumberOfitems]
    FROM
        Orders o
        JOIN
        (
            SELECT
                    [OrderId]
                ,   [Action]
                ,   MIN(ActionTime)
            FROM
                    Orders_Log
            WHERE   
                    [Action] = 'XYZ'
            GROUP BY
                    [OrderId]
                ,   [Action]
    
        ) ordersLog
        ON  o.[OrderId]
            =   
            ordersLog.[OrderID]
    

    我们可以获得更快的东西吗? Orders_Log表中与特定OrderId的特定操作匹配的条目数将在1-50之间变化,其中80%的值在1-8中。

1 个答案:

答案 0 :(得分:2)

查看以下内容是否产生了预期结果...

array (size=3)
  0 => string 'test' (length=4)
  1 => string 'test 3' (length=6)
  2 => string 'test 4' (length=6)

至于挤出最大性能......你可以尝试添加以下索引视图......

SELECT 
    o.OrderId,
    o.[Action],
    o.NumberOfItems,
    xol.FirstAction,
    xol.LastAction
FROM
    dbo.Orders o
    CROSS APPLY (
                SELECT 
                    FirstAction = MIN(ol.ActionTime),
                    LastAction = MAX(ol.ActionTime)
                FROM
                    dbo.Orders_Log ol
                WHERE 
                    o.OrderId = ol.Order_Id
                    AND ol.[Action] = 'XYZ'
                ) xol;

在这种情况下,查询将如下所示......

CREATE VIEW dbo.iv_OrdersLog_FirstLastXYZAction 
WITH SCHEMABINDING AS
    SELECT 
        ol.Orders_Id,
        FirstAction = MIN(ol.ActionTime),
        LastAction = MAX(ol.ActionTime),
        cb = COUNT_BIG(*)
    FROM
        dbo.Orders_Log ol
    WHERE 
        ol.[Action] = 'XYZ'
    GROUP BY 
        ol.Order_Id;
GO

CREATE UNIQUE CLUSTERED INDEX cix_ivOrdersLogFirstLastXYZAction ON dbo.iv_OrdersLog_FirstLastXYZAction (Orders_Id);

HTH, 杰森