2017-02-08 7 views
0

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

 StartDate - datetimeoffset(0); 
    EventDuration - time(0); 
RecurrenceEndDate - datetimeoffset(0); 

99% запросов на этой таблице, потребуется вычисление RecurrenceEndDate + EventDuration.

Этого конкретный запрос, чтобы выбрать только соответствующие записи для определенного анализа будет работать очень, очень часто:

SELECT * FROM RRules WHERE 

**RecurrenceEndDate + EventDuration** >= START_DATE --Make sure last recurrent event did/will not end before START_DATE, which would make the rule irrelevant for the analysis. 

AND StartDate < END_DATE' --Make sure the first occurrence of the event is before END_DATE; 

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

+1

Pinal Dave углубляется в вычисляемые столбцы, и не является черно-белым относительно того, являются ли сохраненные столбцы быстрее. Если вычисление является сложным, то сохранение должно быть более быстрым, иначе неустановленная может быть быстрее. Вот ссылка https://blog.sqlauthority.com/2010/07/27/sql-server-computed-column-persisted-and-storage/ – DeanOC

+0

да стойкие столбцы - это один из вариантов. Может быть, ваши таблицы уже очень тяжелые. Вторая опция заключается в создании встроенного UDF.Как вы сказали, что есть много вычислений, так что это может быть оба варианта. Возможно, ваша структура таблицы неверна. Возможно, так, как вы заполняете таблицу, неправильно , – KumarHarsh

ответ

3

Я хотел бы предложить вам создать computed column:

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

Например, это позволит создать столбец, не сохранялся, что означает расчет происходит каждый раз, когда вы используете колонки:

ALTER TABLE MyTable ADD ChooseABetterName AS (RecurrenceEndDate + EventDuration) 

Или как сохраняемая колонку, которая хранится вместе стороны ваших данных и Безразлично «т должен быть вычислен каждый раз, когда:

ALTER TABLE MyTable ADD ChooseABetterName AS (RecurrenceEndDate + EventDuration) PERSISTED 

Теперь вы можете использовать вычисляемый столбец непосредственно:

SELECT * FROM MyTable WHERE ChooseABetterName >= START_DATE 

Также возможно create indexes on computed columns.

+0

, но разве это не все равно будет определять вычисления каждый раз? Или кешируется вычисленное значение столбца? – victor

+0

Да, он будет вычислять каждый раз, но вы можете сделать столбец PERSISTED, который сохраняет значение (и обновляет его по мере необходимости) – DavidG

+0

Хотя вы можете создать индекс (добавлена ​​ссылка в ответ) – DavidG

0

, но разве это не все равно будет обрабатывать вычисления каждый раз?

Да, это будет. А @DavidG предоставляет right answer. Да, вы можете сохранить вычисляемый столбец, но это далеко не очевидно, что приведет к повышению производительности.

В базе данных производительность достигается за счет минимизации ввода-вывода. Стоимость ввода-вывода в тысячи раз превышает расчеты. Почти все, что вы делаете для замены ввода-вывода с помощью вычислений, - это победа.

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

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

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

+1

БД-механизм позаботится о вычисленных значениях столбцов, OP не придется вычислять эти вручную как таковое :-)) Кстати, это кэш * недействительность * (хронометраж), которая сложна, а не предварительная и извлекающая часть, как в этом случае. – wqw

+1

Также стоит отметить, что без вычисленного столбца механизм БД должен читать столбцы «RecurrenceEndDate» и «EventDuration», чтобы определить результат предложения запроса. Включите индекс в вычисляемый столбец, и он может даже потенциально пропустить кучу строк. – DavidG

0

Создать сохраненный вычисляемый столбец над всем выражением:

alter table RRules 
add column IsRelevant as (cast(case when StartDate + EventDuration >= StartDate then 1 else 0 end as bit)) persisted 

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

+0

START_DATE - это не то же самое, что и StarDate, оно является переменной. – victor

+0

Sry, вы меня сочли, перечисляя стартовую таблицу среди столбцов таблицы. Кроме того, переменные имеют префикс @ в T-SQL. – dean