Эффективность поля, рассчитанная SQL

В моей базе данных есть GUID в качестве первичных ключей, это было сделано для обеспечения уникальности в нескольких системах. (да, я знаю, что 16 байт на строку на таблицу накладных расходов есть и другие варианты, кроме выбора компании)

Чтобы сделать таблицы более удобными, я добавил вычисляемые поля, поэтому, если вы сделаете выбор типа

SELECT * FROM Products

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

например CompanyGUID (сохраняемое поле), CompanyName (вычисляемое поле)

Вычисляемое поле запускается через скалярную функцию, такую ​​как:

CREATE FUNCTION [mySchema].[udf_CompanyNameFromGUID] (@GUID UNIQUEIDENTIFIER)
RETURNS NVARCHAR(MAX)
AS
    BEGIN
        DECLARE @Return NVARCHAR(MAX)
        SELECT  @Return = CompanyName
        FROM    mySchema.Companies
        WHERE   CompanyGUID = @GUID
        RETURN @Return
    END

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

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

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

Заранее спасибо.


person Matthew Baker    schedule 27.10.2017    source источник
comment
Итак, вы добавляете вычисляемые столбцы в свои таблицы с помощью скалярной функции, чтобы упростить задачу разработчику? Разве они не должны просто научиться писать соединение? Похоже, что ввод этого соединения потребует меньше усилий, чем то, что вы пытаетесь сделать.   -  person Sean Lange    schedule 27.10.2017
comment
Честно говоря, я отслеживаю здесь данные так же часто, как и все остальные. Чем более интуитивно понятно, тем лучше. Все парни (и одна девушка), которые тратят время на данные, вполне способны писать соединения, просто нужно делать это снова и снова и снова каждый раз, когда они смотрят. Я лучше сделаю это один раз и больше не буду.   -  person Matthew Baker    schedule 27.10.2017
comment
Или, альтернативно, напишите представление, которое выполняет для них соединения. Обертывание этого в скалярную UDF довольно быстро гарантирует низкую производительность. Это заставит все поиски использовать вложенные циклы RBAR, а также иметь различные проблемы, связанные со скалярными UDF.   -  person Martin Smith    schedule 27.10.2017
comment
Да, я использовал подход с представлениями в предыдущей среде, но пытался не добавлять здесь наворотов. Мы использовали его раньше, потому что разрешили клиенту доступ к схеме представлений, которую мы предварительно оптимизировали для его отчетов SSRS. Последнее, чего мы хотели, это чтобы клиент пытался писать запросы независимо от того, насколько плотной была наша база данных.   -  person Matthew Baker    schedule 27.10.2017


Ответы (2)


Ваша основная проблема с производительностью вызвана не поиском, а SCALAR FUNCTION использованием.

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

Может быть, view - это решение в вашем случае: оно не требует дополнительного места, так как это просто код, который будет расширяться при использовании представления, а внутри представления просто ПРИСОЕДИНЯЙТЕСЬ к вашей таблице с помощью mySchema.Companies:

create view dbo.MyView as
select * -- put here your columns of interest including CompanyName
from dbo.YourTable
     join  mySchema.Companies
         on CompanyGUID = @GUID;
person sepupic    schedule 27.10.2017
comment
Да, я использовал подход с представлениями в предыдущей среде, но пытался не добавлять здесь наворотов. Мы использовали его раньше, потому что разрешили клиенту доступ к схеме представлений, которую мы предварительно оптимизировали для его отчетов SSRS. Последнее, чего мы хотели, это чтобы клиент пытался писать запросы независимо от того, насколько плотной была наша база данных. - person Matthew Baker; 02.11.2017
comment
Извините, я не понял вашей проблемы. Если вы не хотите, чтобы ваш клиент использовал таблицу напрямую, просто запретите выбор на ней, а оставьте разрешение на выбор в представлении. - person sepupic; 02.11.2017
comment
Клиентам уже отказано в доступе, это был просто пример. Это только для нашего внутреннего использования, в основном, когда не-dba необходимо отследить проблемы с данными. Почему я не вижу товар, почему я получаю эту цену. Хотя я считаю справедливым попросить их написать свои собственные запросы, я предпочел бы, чтобы они тратили свое время более продуктивно, если бы я мог придумать лучшую альтернативу. +1 за ответ, но не совсем то, что я ищу. Большое спасибо. - person Matthew Baker; 02.11.2017

Мои рекомендации:

  1. Для столбца companyGUID вы можете сгенерировать и использовать NEWSEQUENTIALID вместо NEWID, это уменьшит фрагментацию. и повысить производительность индекса.
  2. Вы можете сделать столбец CompanyName постоянным, добавив опцию PERSISTED.
person Serkan Arslan    schedule 27.10.2017
comment
ОП заявил, что они используют гиды как способ обеспечения уникальности в разных системах. sequenceid сделал бы это невозможным. На самом деле уникальный идентификатор не так уж плох для первичного ключа, но это не лучший выбор в качестве кластерного индекса. Как вы сказали, фрагментация сходит с ума. - person Sean Lange; 27.10.2017
comment
RE: 2 они не смогут сделать это постоянным. Это не детерминировано. - person Martin Smith; 27.10.2017
comment
Я подумал о сохранении столбца, который повышает производительность, но также влияет на объем требуемого хранилища. Хотя эти поля невелики, они используются только для отладки или отслеживания данных. Приятно видеть, что кто-то идет тем же путем, что и я. Спасибо за вариант. - person Matthew Baker; 27.10.2017