Мы недавно обнаружили проблему производительности с одной из наших систем, и я думаю, что у меня есть фиксация, но я не уверен, что мое понимание корректно.
В самой простой форме у нас есть таблица 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;
Другими словами, представление дает нам среднее значение аккумуляторов, а не сумм. Это также удостоверяется, что мы не получаем деление на нуль в тех случаях, где количество является нулем (эти записи существуют, и нам не разрешают удалить их, так не потрудитесь говорить мне, который они - мусор - Вы проповедуете хору).
Мы заметили что разница во времени между выполнением:
select distinct recdate from XX
варьируется значительно в зависимости от того, используем ли мы таблицу или представление. Я говорю о различии, являющемся 1 секундой для таблицы и 27 секунд для представления (с 100K строками).
Мы на самом деле отследили его назад к select distinct
. То, что, кажется, происходит, - то, что DBMS на самом деле загружает все строки в и сортирует их, чтобы удалить дубликаты. Это достаточно справедливо, это - то, что мы глупо сказали этому делать.
Но я вполне уверен то, что представление включает каждый компонент средств первичного ключа, что невозможно иметь дубликаты так или иначе. Мы проверили проблему с тех пор, если мы создаем другое представление без отличного, это работает на той же скорости как базовая таблица.
Я просто хотел подтвердить свое понимание это a select distinct
не может иметь дубликатов, если это включает все компоненты первичного ключа. Если это так, то мы можем просто изменить представление соответственно.
Да, нет смысла запрашивать отдельных
результатов, когда включены все элементы первичного ключа.
Ограничение первичного ключа таблицы уже исключает дублирование в этих столбцах, но ваша СУБД по-прежнему будет обрабатывать кортежи, чтобы гарантировать их различие.
В этом случае 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;
Поделитесь и наслаждайтесь.
Если представление выбирает непосредственно из одной таблицы и подмножество выбранных столбцов уникальны в таблице, то из этого следует, что выбранные строки будут уникальными в значения и отличные избыточны.