2016-06-02 2 views
1

Я чем-то смущен. Я использую T-SQL и пытается оптимизировать код, который выглядит следующим образом:Вызов функции табличной таблицы T-SQL в несколько раз быстрее, чем вызов один раз?

SELECT * FROM MyTable mt 
LEFT JOIN 
    (SELECT * FROM Table1 t1 
    LEFT JOIN api.tableValuedFunc(@someArgs) tvf 
    on tvf.Key = t1.Key) firstJoin 
on mt.Key = firstJoin.key 
LEFT JOIN 
    (SELECT * FROM Table2 t2 
    LEFT JOIN api.tableValuedFunc(@someArgs) tvf 
    on tvf.Key = t2.Key) secondJoin 
on mt.Key = secondJoin.key 

делая это:

declare @tvfResult TABLE (... some columns ...) 
insert into @tvfResults SELECT * FROM api.tableValuedFunc(@someArgs); 

SELECT * FROM MyTable mt 
LEFT JOIN 
    (SELECT * FROM Table1 t1 
    LEFT JOIN @tvfResults tvf 
    on tvf.Key = t1.Key) firstJoin 
on mt.Key = firstJoin.key 
LEFT JOIN 
    (SELECT * FROM Table2 t2 
    LEFT JOIN @tvfResults tvf 
    on tvf.Key = t2.Key) secondJoin 
on mt.Key = secondJoin.key 

Это удваивает время, необходимое для выполнения! Почему это? Во втором примере я (наивно) предполагаю, что выполняю функцию наполовину так же часто. Существует ли какое-то волшебство SQL, которое происходит за кулисами, которые я разрушаю?

+1

Оглядевшись, это, кажется, связано с https://stackoverflow.com/questions/4109152/table-valued-function-killing-my-query-performance Но рецепт в этом случае использовать временную таблицу, что я и делаю. –

+0

ОК, видимо, это не временная таблица, а переменная таблицы, которая на тонну меньше. Однако все это нужно для работы в функции, поэтому я не могу использовать временные таблицы. Является ли вариант №1 столь же быстрым, как я собираюсь получить? –

+1

Пожалуйста, подтвердите, действительно ли вы используете «SELECT *» в ваших измеренных запросах или просто используете его как стенографию в вопросе. Обратите внимание, что простое использование «SELECT *» может привести к серьезному поражению производительности из-за недоступности любых индексов покрытия. Затем, пожалуйста, приложите ACTUAL QUERY PLAN от SSMS для анализа. Как мы можем определить, что происходит без плана запроса или полного DDL для всех таблиц/представлений и т. Д.? –

ответ

1

Вместо создания переменной таблицы создать локальную временную таблицу может повысить производительность, если она выводит большое количество строк.

create table #tvfResult (... some columns ...) 

insert into #tvfResults SELECT * FROM api.tableValuedFunc(@someArgs); 

SELECT * FROM MyTable mt 
LEFT JOIN 
    (SELECT * FROM Table1 t1 
    LEFT JOIN #tvfResults tvf 
    on tvf.Key = t1.Key) firstJoin 
on mt.Key = firstJoin.key 
LEFT JOIN 
    (SELECT * FROM Table2 t2 
    LEFT JOIN #tvfResults tvf 
    on tvf.Key = t2.Key) secondJoin 
on mt.Key = secondJoin.key 

Локальные временные таблицы видны только их создателям в течение того же подключения к экземпляру SQL Server, как, когда таблицы были созданы первыми или ссылки. Локальные временные таблицы удаляются после отключения пользователя из экземпляра SQL Server.

Оставьте временную таблицу явно, если вы повторно используете запрос с тем же сеансом.

drop table #tvfResult 
+1

Я хочу сделать это, но все это должно жить внутри самой функции, поэтому, к сожалению, временная таблица недоступна. –

+0

вы можете создать локальную временную таблицу внутри функции, не так ли? – ydoow

+1

Я так и думал, но SQL-сервер вызывает ошибку: не удается получить доступ к временным таблицам изнутри функции. –

0

Обратите внимание, что, если вы не пропущены несколько важных факторов, от вашего вопроса, ваш первый запрос сводится к просто:

SELECT * FROM MyTable mt 
LEFT JOIN Table1 t1 on mt.Key = t1.key 
LEFT JOIN Table2 t2 on mt.Key = t2.key 
LEFT JOIN api.tableValuedFunc(@someArgs) tvf1 on tvf1.Key = t1.key 
LEFT JOIN api.tableValuedFunc(@someArgs) tvf2 on tvf2.Key = t2.key 

Теперь анализ сводится к тому, что фактический выбор вашего столбца в SELECT, - пожалуйста, предоставьте эти детали, так как невозможно проанализировать ваш запрос, не зная, что такое запрос, - в мучительной детали, потому что проблемы с производительностью неизменно находятся в деталях.

+0

Я удалил справедливую сумму из-за функции, о которой идет речь, длиной более 600 строк. Вот план выполнения для него как есть: http://pastebin.com/7Y4axtKB И с моей неправильной оптимизацией: http://pastebin.com/NZuZHkY1 –

Смежные вопросы