Правильно ли мое понимание слова «выбрать отдельное»? - PullRequest
6 голосов
/ 03 мая 2010

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

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

recdate   date
rectime   time
system    varchar(20)
count     integer
accum1    integer
accum2    integer

Аккумуляторов гораздо больше, чем они, но все они одной формы. Первичный ключ состоит из recdate, rectime и system.

Когда значения собираются в таблицу, счетчик для данного recdate/rectime/system увеличивается, а значения для этого ключа добавляются в накопители. Это означает, что средние значения могут быть получены с помощью accumN / count.

Теперь у нас также есть вид на эту таблицу, указанный следующим образом:

create view blah_v (
    recdate, rectime, system, count,
    accum1,
    accum2
) as select distinct
    recdate, rectime, system, count,
    value (case when count > 0 then accum1 / count end, 0),
    value (case when count > 0 then accum2 / count end, 0)
    from blah;

Другими словами, представление дает нам среднее значение аккумуляторов, а не суммы. Это также гарантирует, что мы не получим деление на ноль в тех случаях, когда число равно нулю (эти записи do существуют, и нам не разрешено их удалять, поэтому не говорите мне, что они Мусор - вы проповедуете в хоре).

Мы заметили, что разница во времени между выполнением:

select distinct recdate from XX

сильно зависит от того, используем ли мы таблицу или представление. Я говорю о разнице в 1 секунду для таблицы и 27 секунд для представления (с 100К строк).

Мы на самом деле отследили его до select distinct. Кажется, что происходит то, что СУБД фактически загружает все строки и сортирует их, чтобы удалить дубликаты. Это достаточно справедливо, это то, что мы глупо сказали, чтобы это делало.

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

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

Ответы [ 3 ]

4 голосов
/ 03 мая 2010

В этом случае DISTINCT не приносит вам пользы, потому что ваши отдельные поля уже гарантированно будут уникальными из-за ограничения PRIMARY KEY для базовой таблицы. Вы можете попробовать переписать представление как:

create view blah_v ( 
    recdate, rectime, system, count, 
    accum1, 
    accum2 
) as select
       recdate, rectime, system, count, 
       case when count > 0 then accum1 / count else 0 end,
       case when count > 0 then accum2 / count else 0 end,
       from blah;

Делись и наслаждайся.

3 голосов
/ 03 мая 2010

Да, нет смысла запрашивать distinct результаты, когда включены все элементы первичного ключа.

Ограничение первичного ключа таблицы уже исключает дубликаты в этих столбцах, но ваша СУБД все равно будет обрабатывать кортежи, чтобы убедиться, что они различны.

2 голосов
/ 03 мая 2010

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

...