2

Dans SQLSERVER 2005, j'utilise la fonction table comme un moyen pratique d'effectuer une agrégation arbitraire sur des données de sous-ensemble à partir d'une grande table (en passant la plage de dates ou de tels paramètres). J'utilise ces thèses à l'intérieur de requêtes plus volumineuses en tant que calculs joints et je me demande si l'optimiseur de plan de requête fonctionne bien avec eux dans toutes les conditions ou si je suis préférable d'ignorer un tel calcul dans mes requêtes plus volumineuses.L'optimiseur de plan de requête fonctionne-t-il correctement avec les fonctions table jointes/filtrées?

  1. Est-ce que optimiseur plan de requête unnest fonctions table si elle fait sens?
  2. Si ce n'est pas le cas, qu'est-ce que vous recommandez d'éviter la duplication de code qui se produirait manuellement en les désinstallant?
  3. Si c'est le cas, comment vous identifiez-vous à partir du plan d'exécution ?
exemple de code

:

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] 

J'espère que l'échantillon a du sens.

Merci beaucoup pour votre aide!

Répondre

5

Dans ce cas, il s'agit d'une "fonction de table en ligne" L'optimiseur étend simplement (unnests) s'il est utile (ou vue).

Si la fonction est traitée comme une "boîte noire" par la requête externe, le moyen le plus rapide est de comparer les E/S affichées dans SSMS et les E/S dans le profileur. Profler capture les E/S «boîte noire» que SSMS ne fait pas.

Blog post by Adam Mechanic (son livre est dans mon tiroir au travail)

3

1) Oui, en utilisant votre syntaxe, il le fait. S'il vous arrivait d'utiliser un UDF qui renvoyait une table avec une logique conditionnelle, ce ne serait pas le cas.

3) L'optimiseur ne précise pas quelle partie de votre requête il optimise, car il peut sembler bon de combiner des blocs du plan avec votre fonction, ou d'optimiser les bits.