Domanda

In SQLSERVER 2005, sto usando la funzione con valori di tabella come modo conveniente per eseguire aggregazioni arbitrarie su dati di sottoinsiemi da tabelle di grandi dimensioni (passando l'intervallo di date o tali parametri).

Sto usando queste tesi all'interno di query più grandi come calcoli uniti e mi chiedo se l'ottimizzatore del piano di query funziona bene con loro in ogni condizione o se sono meglio annullare tale calcolo nelle mie query più grandi.

  1. L'ottimizzatore del piano di query è più inutile funzioni con valori di tabella se lo fanno senso?
  2. In caso contrario, cosa fai consiglia di evitare la duplicazione del codice ciò si verificherebbe manualmente infastidirli?
  3. In caso affermativo, come fare lo identifichi dall'esecuzione pianificare?

esempio di codice:

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]

Spero che il campione abbia un senso.

Mille grazie per il tuo aiuto!

È stato utile?

Soluzione

In questo caso, è una funzione con valore di tabella inline " L'ottimizzatore semplicemente lo espande (annulla) se è utile (o visualizza).

Se la funzione è considerata come "scatola nera" dalla query esterna, il modo più rapido è confrontare IO mostrato in SSMS e IO in profiler. Profler cattura "scatola nera" IO che SSMS non lo fa.

Post di blog di Adam Mechanic (il suo libro è nel mio cassetto al lavoro)

Altri suggerimenti

1) Sì, usando la sintassi, lo fa. Se ti è capitato di usare un UDF che ha restituito una tabella con una logica condizionale, non lo farebbe.

3) L'ottimizzatore non indicherà quale parte della query sta ottimizzando, perché potrebbe risultare opportuno combinare blocchi del piano con la tua funzione o ottimizzare i bit di distanza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top