查询计划优化器是否适用于已连接/已过滤的表值函数?

时间:2008-11-22 07:30:42

标签: sql-server sql-server-2005 tsql query-optimization user-defined-functions

在SQLSERVER 2005中,我使用表值函数作为从大表(传递日期范围或此类参数)对子集数据执行任意聚合的便捷方式。

我在大型查询中使用这些作为联合计算,我想知道查询计划优化器是否在每种情况下都能很好地与它们配合使用,或者我是否更好地在我的大型查询中不需要这样的计算。

  1. 查询计划优化器是否已取消 表值函数,如果它 感?
  2. 如果没有,你是什么人 建议避免代码重复 这将通过手动发生 不要他们?
  3. 如果是,怎么做 你从执行中识别出来 计划?
  4. 代码示例:

    create table dbo.customers (
        [key] uniqueidentifier
        , constraint pk_dbo_customers
            primary key ([key])
    )
    go
    
    /* assume large amount of data */
    create table dbo.point_of_sales (
        [key] uniqueidentifier
        , customer_key uniqueidentifier
        , constraint pk_dbo_point_of_sales
            primary key ([key])
    )
    go
    
    create table dbo.product_ranges (
        [key] uniqueidentifier
        , constraint pk_dbo_product_ranges
            primary key ([key])
    )
    go
    
    create table dbo.products (
        [key] uniqueidentifier
        , product_range_key uniqueidentifier
        , release_date datetime
        , constraint pk_dbo_products 
            primary key ([key])
        , constraint fk_dbo_products_product_range_key 
            foreign key (product_range_key) 
            references dbo.product_ranges ([key])
    )
    go
    

    /* assume large amount of data */
    create table dbo.sales_history (
        [key] uniqueidentifier
        , product_key uniqueidentifier
        , point_of_sale_key uniqueidentifier
        , accounting_date datetime
        , amount money
        , quantity int
        , constraint pk_dbo_sales_history
            primary key ([key])
        , constraint fk_dbo_sales_history_product_key
            foreign key (product_key)
            references dbo.products ([key])
        , constraint fk_dbo_sales_history_point_of_sale_key
            foreign key (point_of_sale_key)
            references dbo.point_of_sales ([key])
    )
    go
    
    create function dbo.f_sales_history_..snip.._date_range
    (
        @accountingdatelowerbound datetime,
             @accountingdateupperbound datetime
    )
    returns table as
    return (
        select
                      pos.customer_key
            , sh.product_key
            , sum(sh.amount) amount
            , sum(sh.quantity) quantity
        from 
            dbo.point_of_sales pos
            inner join dbo.sales_history sh 
                on sh.point_of_sale_key = pos.[key]
        where
                      sh.accounting_date between 
                          @accountingdatelowerbound and 
                          @accountingdateupperbound
        group by
                      pos.customer_key
                      , sh.product_key
    )
    go
    
    -- TODO: insert some data
    
    -- this is a table containing a selection of product ranges
    declare @selectedproductranges table([key] uniqueidentifier)
    
    -- this is a table containing a selection of customers
    declare @selectedcustomers table([key] uniqueidentifier)
    
    declare @low datetime
        , @up datetime
    
    -- TODO: set top query parameters
    

    select
             saleshistory.customer_key
             , saleshistory.product_key
             , saleshistory.amount
             , saleshistory.quantity
    from
             dbo.products p
             inner join @selectedproductranges productrangeselection 
                 on p.product_range_key = productrangeselection.[key]
             inner join @selectedcustomers customerselection on 1 = 1
             inner join 
             dbo.f_sales_history_..snip.._date_range(@low, @up) saleshistory
                 on saleshistory.product_key = p.[key]
                 and saleshistory.customer_key = customerselection.[key]
    

    我希望样本有意义。

    非常感谢你的帮助!

2 个答案:

答案 0 :(得分:5)

在这种情况下,它是“内联表值函数” 如果有用(或查看),优化器只会扩展(不相容)它。

如果外部查询将该函数视为“黑盒子”,则最快的方法是比较分析器中SSMS与IO中显示的IO。 Profler捕获了SSMS没有的“黑匣子”IO。

Blog post by Adam Mechanic(他的书出现在我工作的抽屉里)

答案 1 :(得分:3)

1)是的,使用你的语法,确实如此。如果您碰巧使用返回其中包含条件逻辑的表的UDF,则不会。

3)优化器不会指出它正在优化的查询的哪一部分,因为它可能适合将计划的块与您的函数组合,或者优化位。