Это неэффективный способ написать запрос SQL? - PullRequest
3 голосов
/ 02 октября 2011

Предположим, у меня был вид, подобный этому:

CREATE VIEW EmployeeView 
AS
 SELECT ID, Name, Salary(PaymentPlanID) AS Payment
 FROM Employees

Пользовательская функция, Salary, несколько дорогая.

Если бы я хотел сделать что-то подобное,

SELECT *
FROM TempWorkers t
  INNER JOIN EmployeeView e ON t.ID = e.ID

будет ли Salary выполняться в каждой строке Employees или сначала будет выполняться объединение, а затем вызываться только в строках, отфильтрованных в результате объединения? Могу ли я ожидать того же поведения, если EmployeeView был подзапросом или табличной функцией вместо представления?

Ответы [ 3 ]

4 голосов
/ 02 октября 2011

Функция будет вызываться только при необходимости. Если ваш последний оператор выбора не включает это поле, он вообще не вызывается. Если ваш окончательный выбор относится к 1% вашей таблицы, он будет вызван только для этого 1% таблицы.

Это фактически то же самое для подзапросов / встроенных представлений. Вы можете указать функцию для поля в подзапросе, затем никогда не использовать это поле, и в этом случае функция никогда не вызывается.


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

SELECT
  myTable.*,
  myFunction.Value
FROM
  myTable
CROSS APPLY
  myFunction(myTable.field1, myTable.field2) as myFunction

До тех пор, пока MyFunction является Inline (не мультисостоянием) и возвращает только одну строку для каждого набора входов, это часто масштабируется намного лучше, чем Scalar Functions.


Это немного отличается от превращения всего представления в табличную функцию, которая возвращает много строк.

Если такой TVF является многоуровневым, он будет вызывать функцию Зарплата для каждой записи. Но встроенные функции могут быть расширены встроенными, как будто макрос SQL, и поэтому вызывать Salary только по мере необходимости; нравится вид.

Как общее правило для TVF, не возвращайте записи, которые затем будут отброшены.

1 голос
/ 02 октября 2011

Должна выполняться только функция Зарплата для соединенных строк. Но вы больше не фильтруете таблицы. Если ID - это столбец внешнего ключа, а не NULL, он будет выполнять эту функцию для всех строк. Фактический план выполнения - хорошее место, чтобы увидеть наверняка.

0 голосов
/ 02 октября 2011

Как сказано выше, функция будет вызываться только для соответствующих строк.Чтобы получить дополнительные вопросы и получить действительно хорошее представление о том, что происходит , вам необходимо собрать данные о производительности либо с помощью SQL Profiler, либо путем просмотра реального плана выполнения и истекшего времени.Затем протестируйте несколько теорий и найдите, какая из них является наилучшей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...