Comments 46
Ожидал увидеть что-нибудь похардкорнее, типа разбиение на партиции/подтаблицы, выключение индексов на время инсерта, анализ физического расположения записываемых данных с целью их максимального эффективного группирования, прединсертные сортировки и т.п.
В общем странная статья, зачем ее было переводить…
Из вашего комментария я выделил для себя больше полезного в виде направлений, над чем можно думать, чем из статьи:)
Вопросы не риторические и без сарказма, хотелось бы узнать, как решают при таком подходе описанные мной проблемы.
Но тут могут повлиять внешние факторы. Например этих нескольких минут на построение индекса может просто не быть, так как блокировка недопустима. В этих случаях может помочь
— разбиение на подтаблицы,
— hot swap таблиц путем переименования,
— доступ к данным через VIEW, который тоже можно переопределить мгновенно в зависимости от того, в каких таблицах в данный момент данные и индексы актуальны.
Еще можно предварительно создавать записи-placeholder-ы в индексировнной таблице, задав тем самым значения индексов для непоступивших еще данных, а при поступлении уже апдейтить какие-надо неиндексированные поля. Такой прием позволяет физически группировать записи в тот же самый блоке на диске, и потом прочитать их горздо быстрее, чем если бы записи были созданы в разное время и в разных блоках.
В общем поле извращений тут большое.
Вставка в таблицу без индексов обычно мгновенна и не зависит от размеров таблицы
В постгре это точно не так и зависит от огромного количества факторов. В частности от интенсивности чтения, изменения и собственно самой записи.
Построение индекса на миллионах записей всегда быстрее, чем миллионы вставок в упорядоченную структуру
Миллион вставок всегда будут очень медленными. А если вставить батчем, то это утверждение может быть верным далеко не всегда.
Остальные советы тоже хороши в ограниченном количестве случаев. Например, если работаете с финансами так лучше не делать :)
Остальные советы тоже хороши в ограниченном количестве случаев. Например, если работаете с финансами так лучше не делать :)«Остальные советы» реализовывались как раз в финансах в телеком-биллинге. Там вообще это стандартная практика — копить транзакции за разные месяцы в отдельных таблицах. Там же пробовали и записи-плейсхолдеры. Они во много раз увеличивали скорость формирования стейтментов в конце месяца, так как данные каждого клиента были уже сгруппированы на диске, но естественно пришлось заплатить цену: загрузка системы при записи возрасла в разы, ну и какое-то количество плейсхолдеров оставалось неиспользованными, и БД слегка увеличилась.
Поэтому да, надо смотреть весь цикл жизни данных, в каком порядке ожидается поступление данных, когда, как часто и по каким критериям будет происходить чтение, насколько каждая из этих операций критична по времени, по целостности, какое есть железо, какая нужна надежность, требуемое время восстановления, и т.д. и т.п. И тогда уж принимать решение.
Подробней в документации
А pg и pg-native отличаются тем, что первый полностью на js написан, а второй обращается к сишной библиотеке, второй чуть-чуть быстрее.
Если надо ещё ускорить попробуйте (мой) pg-adapter
paramFormats[]
Specifies whether parameters are text (put a zero in the array entry for the corresponding parameter) or binary (put a one in the array entry for the corresponding parameter). If the array pointer is null then all parameters are presumed to be text strings.
Values passed in binary format require knowledge of the internal representation expected by the backend. For example, integers must be passed in network byte order. Passing numeric values requires knowledge of the server storage format, as implemented in src/backend/utils/adt/numeric.c::numeric_send() and src/backend/utils/adt/numeric.c::numeric_recv().
как всего одно изменение привело к росту производительности в 9 раз
Ожидание — неожиданная конфигурация PSQL, интересный способ разбивки данных…
Реальность — оказывается можно объединить несколько вставок в одну.
Статья вполне ок — автор описал свой реальный опыт и грабли, на которые наступил.
2. Хранить метку времени в поле TEXT?? Почитайте про типы timestamp и timestamptz.
3. А для group_id зачем TEXT? Почти наверняка там строки вполне предсказуемой длины.
Этот товарищ, кроме своего пет-проекта actual еще и работает в stripe.
Но это не главное.
Он тот, кто придумал prettier.
Это позор автора.
Статья не стоила времени, затраченного на перевод.
James Long is a developer & designer with over a decade of experience building large-scale applications.
P.S. Еще теплилась надежда, что в stripe он пришел на позиции джуна. Но нет "I talked to Alex Sexton 5 years ago about joining Stripe".
Из текста следует что параметры запроса интерполируются в строку запроса.Если бы это не делалось и использовался бы параметрический запрос то можно было бы и на окна не разбивать.
К правильным комментариям выше я бы добавил UUID в качестве первичного ключа. И генерация его на клиенте. Ждать ответа от бека при этом не нужно. Можно на сервере реализовать вставку через очередь.
При этом мы в целом уменьшаем размеры индекса по первичному ключу. Чем больше столбцов и чем более объёмные там типы данных, тем больше получается индекс, но это спорное утверждение, местами может быть и меньше.
Другой вопрос, что суррогатные ключ в виде автоинкрементных идентификаторов или UUID-ов удобным на практике в том числе и не разрабам. Второй мотив использования суррогатных ключей — зачастую сложность в выделении естественного ключа, а иногда и невозможности это сделать.
Другая же проблема на мой взгляд, которая как раз перекликается с невозможностью выделения естественного ключа — требование практического анализа большого объёма данных для проверки высказываний экспертов. Я очень часто сталкиваюсь с ситуацией, когда вроде бы эксперты говорят, что дублирования быть не может, но при анализе на предмет поиска как раз ситуаций, которых быть не может несколько таких не найдётся.
Поэтому на мой взгляд суррогатный ключ это прям обязательная вещь, ведь нельзя спроектировать прям идеальную систему.
Ну и как заметил GooG2e, бывают ситуации когда естественные ключи перестают быть уникальными. Имхо, достаточно столкнуться с одним таким случаем на своей практике в проде на большой базе, чтоб перестать даже думать использовать естественные ключи.
Вообще больше похоже на статью, как я делал и как делать не стоит.
Если приложение предполагает высокую нагрузку то всё сделано не верно.
На наших проектах мы прокачивам по несколько сотен тысяч записей в бд на обновление и вставку.
При этом постгресс не испытывает видимых усилий.
Любой проект и задача начинаеться с анализов механизмов и возможностей инструментов, а не со статьи на хабре как я открыл для себя америку.
PostgreSQL: как всего одно изменение привело к росту производительности в 9 раз