#sql #amazon-redshift
#sql #amazon-redshift
Вопрос:
Я ищу самый быстрый способ получить 1-ю запись (столбцы a, b, c) для каждого раздела (a, b) с использованием SQL. Таблица состоит из ~ 10 000 000 строк.
Подход # 1:
SELECT * FROM (
SELECT a,b,c,
ROW_NUMBER() OVER ( PARTITION by a, b ORDER BY date DESC) as row_num
FROM T
) WHERE row_num =1
Но это, вероятно, выполняет дополнительную работу за сценой — мне нужна только 1-я строка для каждого раздела.
Подход № 2 с использованием FIRST_VALUE(). Поскольку FIRST_VALUE() возвращает выражение, позвольте упаковать / объединить a, b, c, используя некоторый разделитель, в одно выражение, например:
SELECT FIRST_VALUE(a ',' 'b' ',' c)
OVER ( PARTITION by a, b ORDER BY date DESC rows unbounded preceding) FROM T
Но в этом случае мне нужно распаковать результат, что является дополнительным шагом.
Подход № 3 с использованием FIRST_VALUE() — повторите (…) для a , b :
SELECT
FIRST_VALUE(a)
OVER ( PARTITION by a, b ORDER BY date DESC rows unbounded preceding),
FIRST_VALUE(b)
OVER ( PARTITION by a, b ORDER BY date DESC rows unbounded preceding),
c
FROM T
В подходе № 3 я не знаю, достаточно ли умен database engine (Redshift) для разделения только один раз
Комментарии:
1. вы действительно пробовали запускать их? У нас не очень жесткие требования к производительности, и мы часто используем подход № 3 даже с 10 столбцами событий, использующими одно и то же окно. Я всегда был убежден, что механизм запросов достаточно умен, чтобы заметить одно и то же определение окна и способен повторно использовать (хотя доказательств нет). Также то, что мы обычно делаем, это
SELECT DISTINCT
window functions over columns
— в противном случае вы получаете тонны дубликатов2. Вы пробовали сравнивать запросы? Мне любопытно, каковы последствия каждого решения для производительности.
3. » Мне нужна только 1-я строка для каждого раздела » вы, кажется, ожидаете здесь какой-то возможности быстрого доступа к базе данных. Это не так. Для надежного поиска «первой строки» у базы данных нет альтернативы сортировке всех строк в разделе, она не может использовать короткий путь. Если вы хотите знать, какой вариант является самым быстрым, проверьте план выполнения. Кстати: другим вариантом было бы использовать объединение с производной таблицей: pastebin.com/z7CV7FKD
Ответ №1:
Первый запрос отличается от двух других. Первый возвращает только одну строку для каждой группы. Два других возвращают те же строки, что и в исходном запросе.
Вы должны использовать версию, которая делает то, что вы хотите, которая, я полагаю, является первой. Если вы добавите select distinct
or group by
к другим запросам, это, вероятно, добавит накладные расходы, которые сделают их медленнее — но вы можете проверить свои данные, чтобы убедиться, что это правда.
Ваша интуиция верна, что первый запрос выполняет ненужную работу. В базах данных, которые полностью поддерживают индексы, коррелированный подзапрос часто выполняется быстрее. Однако я не думаю, что это имело бы место в Redshift.