Хорошо ли оптимизатор планов запросов работает с Объединенными / отфильтрованными табличными функциями?
В SQLSERVER 2005 я использую табличную функцию как удобный способ выполнить произвольную агрегацию данных подмножества из большой таблицы (передавая диапазон дат или такие параметры).
Я использую тезисы внутри больших запросов в качестве объединенных вычислений, и мне интересно, хорошо ли оптимизатор плана запросов работает с ними в каждом условии или мне лучше отменить такие вычисления в моих больших запросах.
- делает ли query plan optimizer unnest таблично-значные функции, если это делать смысл?
- Если это не так, что вы делаете рекомендуем избегать дублирования кода это произойдет вручную лишить их присутствия духа?
- если да, то как это сделать вы определяете это по исполнению план?
Пример кода:
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 ответа:
В данном случае это " встроенная табличная функция" Оптимизатор просто разворачивает (отменяет) его, если он полезен (или вид).
Если функция обрабатывается внешним запросом как "черный ящик", самый быстрый способ-сравнить IO, показанный в SSMS, с IO в profiler. Profler фиксирует "черный ящик" Ио, что среда SSMS не.
Сообщение в блоге Адама механика (его книга находится в моем ящике на работе)
1) Да, используя ваш синтаксис, это так. Если вы случайно используете UDF, который возвращает таблицу, в которой есть условная логика, это не будет, хотя.
3) оптимизатор не будет указывать, какую часть вашего запроса он оптимизирует, потому что он может посчитать целесообразным объединить фрагменты плана с вашей функцией или оптимизировать биты.