Как стать автором
Обновить

Комментарии 17

CREATE UNIQUE INDEX ON events(ts DESC, id DESC);


Зачем здесь UNIQUE? id, как я понимаю, уже Primary Key, от добавления колонок он не потеряет уникальности. Дополнительная проверка уникальности не даёт лишней нагрузки на базу при INSERT?
Зачем здесь UNIQUE?
Исключительно для наглядности — мы ведь тут не ведем речь о производительности вставки в БД.

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

Увы, не поможет если навигация допускается на произвольную страницу (а не только на следущую/предыдущую), без offset/limit тут уже никак (если только не гарантировать сквозную нумерацию в id).

Тогда возникает вопрос — а нужен ли действительно переход именно «на страницу» или таки достаточно «по координатам». Ну или как-то загодя нумеровать (и перенумеровывать потом) весь набор.
Загодя нумеровать кажется не получится, если интерфейс позволяет десятки вариантов фильтров и сортировок, до куче в кластере из нескольких серверов.
Если допустимо оставить крайние «страницы» неполными, то можно ведь разбить на какие-то предметные интервалы — скажем, таймлайн — на минуты, и адресоваться к ним. Тогда на каждой «странице» будет заведомо один интервал, хоть и с непостоянным кол-вом записей
Было бы интересно почитать про более сложные случаи. Например когда у вас таблица содержит сотни тысяч записей, уникальный ключ и 5-10 полей значений по которым может производиться фильтрация/сортировка. Мы вот как раз живем в таких условиях. B SQL у нас нет (
Тут надо очень хорошо ориентироваться в предметной области. Например, как часто изменяется/добавляются записи в таблицу, какие возможны комбинации фильтров, все ли из них должны работать «идеально быстро»,…
И не все из этих вариантов вообще решаются с помощью SQL.
Ну если брать наши случаи, то есть как раз два варианта:
1) Записи создаются и не обновляются
2) Записи создаются и часто изменяются (специфические документы, проходящие разные стадии привязки, дополнения, одобрения и т.п.)

При этом у нас записи НИКОГДА не удаляются.

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

Было бы интересно узнать больше о способах решения подобного класса задач. И в том числе о решениях не с помощью SQL, SQL у нас нет.

Если говорить о наших решениях (которые крайне все таки специфичны ввиду недоступности SQL, хотя СУБД и реляционная), то мы пока остановились на создании индексов покрывающих хотя бы по одному критерию (максимум двум), и проходу с помощью мммм… проблемы терминологического характера… курсора скорее всего. Наша сложность еще в том, что одним из требований является знание об общем числе записей отвечающих этим фильтрам.
Первый кейс неплохо покрывает clickhouse. Второй кейс тоже, если сможете адаптировать архитектуру под первый кейс — там есть специальные штуки.
Фильтры и их комбинации по сути комбинаторные, т.е произвольные сочетания произвольного количества фильтров с произвольным порядком сортировки
В таких условиях лучше всего себя покажет полная материализация всех возможных комбинаций. :)

На самом деле, поисковые движки типа Sphinx, ElasticSearch «внутри» ровно это и делают. Только не всегда «полную» материализацию.

Пару лет назад читал где-то, что Я.Маркет как раз делает in-memory-материализацию результатов поиска, поэтому все фильтры-поиски идеально быстры, но первичное построение индекса занимает дни. Возможно, что-то уже изменилось.
У меня слишком много комбинаций в такой схеме получается и сильно проседает запись. В пиках запись 500МБ/с при отдельных индексах на всех фильтруемых колонках, если ещё и материализовать — будет совсем треш.
При таком объеме записи не надо давать пользователям хотеть «все возможные комбинации». Как только перестать такое хотеть, можно достаточно несложно «заточить» индексы по конкретные наиболее типовые выборки.
Иначе это путь в большие кластеры из много-много серверов.
Если наступает перехотеть — тогда clickhouse начинает лучше выполнять эту задачу… Поэтому пока живём с limit offset и без count всей выборки.
clickhouse начинает лучше выполнять эту задачу

А вот это очень сильно зависит от задачи. Как известно, CH плохо относится к UPDATE, поэтому если ваши выборки должны строиться по накапливающимся агрегатам…

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

А вариант 3 точно лучше второго?

Если мы говорим в целом о базе — безусловно. Индекс более компактен (одно поле вместо двух), что положительно сказывается как при Insert/Update, так и при чтении. Да еще и объем меньше на хранилище.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий