Как стать автором
Обновить
193
95.2
Боровиков Кирилл @Kilor

Архитектура ИС: PostgreSQL, Node.js и highload

Отправить сообщение

Node.js: Клонирование ключей. Is eval() evil?

Время на прочтение5 мин
Количество просмотров3.2K

На примере простой задачи клонирования ключей объекта посмотрим, есть ли реальные альтернативы по производительности столь презираемой JavaScript-разработчиками функции eval().

Подобная задача возникает, если оригинальное значение ключа надо оставить у объекта, а как-то обработанное - положить рядом в новый соответствующий ключ. То есть, для начала, из {"a" : 1, "b" : 2} надо получить {"a" : 1, "a-copy" : 1, "b" : 2, "b-copy" : 2}.

Пару лет назад я уже рассказывал, почему максимальная производительность подобных операций на JavaScript важна для нашего сервиса потокового анализа логов PostgreSQL, как можно поускорять парсинг с помощью WebAssembly, и вот сегодня - продолжение.

Читать далее
Всего голосов 12: ↑12 и ↓0+12
Комментарии12

PostgreSQL Antipatterns: Индиана Джонс и максимальное значение ключа, или В поисках «последних» записей

Время на прочтение2 мин
Количество просмотров10K

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

Кажется, что тут и споткнуться-то негде в реализации - но все оказывается совсем не тривиально.

Читать далее
Всего голосов 18: ↑16 и ↓2+20
Комментарии42

PostgreSQL в «Тензоре» — публикации за год (#3)

Время на прочтение3 мин
Количество просмотров3.6K

Под занавес уходящего года предлагаю традиционно вспомнить, про какие интересные возможности и особенности работы с PostgreSQL мы рассказали в нашем блоге.

Если не видели дайджест за прошлый год — время наверстать упущенное!

Читать далее
Всего голосов 6: ↑6 и ↓0+6
Комментарии0

DBA: хранение списков — таблица, массив, строка?

Время на прочтение4 мин
Количество просмотров15K

Достаточно часто при проектировании схемы БД возникает задача сохранить по основной сущности некоторый набор простых второстепенных данных.

Например, это могут быть ФИО сотрудников, принимающих участие во встрече, список приложенных к сообщению файлов или перечень отгружаемых по документу позиций.

Во всех этих случаях мы заранее понимаем, что список этот меняется редко и ни индексировать эти данные, ни искать по ним, ни извлекать отдельно от основной сущности (встречи, сообщения или документа), мы не захотим.

Давайте посмотрим, какие варианты хранения таких данных мы можем использовать в PostgreSQL, и какой из них окажется в разы более эффективным.

Читать далее
Всего голосов 19: ↑15 и ↓4+14
Комментарии21

PostgreSQL Antipatterns: простой(?) INSERT… VALUES

Время на прочтение3 мин
Количество просмотров17K

Представим, что у вас есть некоторая табличка статистики, куда вы периодически скидываете таймстамп последнего "текущего" состояния в паре координат - например, (ID организации, ID сотрудника).

Как больно наступить на грабли в совсем простом, казалось бы, запросе?

Читать далее
Всего голосов 37: ↑33 и ↓4+35
Комментарии32

PostgreSQL, что в логе твоем?

Время на прочтение3 мин
Количество просмотров11K

Наверняка, многие из вас пользуются explain.tensor.ru - нашим сервисом визуализации PostgreSQL-планов или уже даже развернули его на своей площадке. Но визуализация конкретного плана - это лишь небольшая помощь разработчику, поэтому в "Тензоре" мы создали сервис, который позволяет увидеть сразу многие аспекты работы сервера: медленные или гигантские запросы, возникающие блокировки и ошибки, частоту и результаты проходов [auto]VACUUM/ANALYZE.

И сегодня мы, наконец, готовы представить вам демо-режим этого сервиса, куда вы самостоятельно можете загрузить лог своего PostgreSQL-сервера и наглядно увидеть, чем он у вас занимается.

Читать далее
Всего голосов 29: ↑29 и ↓0+29
Комментарии12

Приручаем многопоточность в Node.js (часть 5/5: автомасштабирование под нагрузку)

Время на прочтение19 мин
Количество просмотров7.5K

В прошлых частях цикла мы:

- рассмотрели базовые концепты работы с многопоточностью в JavaScript на примере среды Node.js;

- научились формировать общую очередь и каналы обмена данными и сигналами, чтобы более эффективно управлять загрузкой потоков;

- использовали разделяемую память и Atomics-операции как самое быстрое средство обмена большими блоками данных;

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

В сегодняшней, заключительной, части я продемонстрирую, как все эти механики вместе позволяют сделать эффективный микросервис, автоматически подстраивающийся под изменения входящей нагрузки.

В данном случае эффективность - это не про максимально возможную скорость обработки каждой отдельной задачи, а про сбалансированное использование аппаратных ресурсов с учетом тех ограничений, на которые мы готовы пойти. Особенно актуально это для различных "облачных" размещений, где оплата идет за фактически потребленные CPU и RAM.

Читать далее
Всего голосов 15: ↑15 и ↓0+15
Комментарии6

Приручаем многопоточность в Node.js (часть 4/5: координатор против синхронного кода)

Время на прочтение11 мин
Количество просмотров4.7K

В предыдущей части мы научились эффективно передавать данные вспомогательным потокам из основного через разделяемую память, используя Atomics-операции и блокировки.

Но мы рассматривали все-таки идеальную ситуацию, когда основной поток больше ничем не занимался, кроме обмена с "подчиненными" уже заранее готовыми данными. В реальных же приложениях такое встречается достаточно редко - обычно эти самые данные приходится готовить непосредственно перед передачей. И, бывает, в этом участвует существенная доля синхронного кода, что для JavaScript крайне неприятно, но иногда неизбежно - например, при вычислении регулярных выражений.

Давайте оценим, насколько синхронные операции "роняют" производительность нашего тестового приложения. И узнаем, как можно в разы улучшить ее, "скрестив ужа с ежом", используя выделенный поток-координатор из позапрошлой части статьи совместно с разделяемой памятью.

Читать далее
Всего голосов 15: ↑13 и ↓2+13
Комментарии12

Приручаем многопоточность в Node.js (часть 3/5: разделяемая память, атомарные операции и блокировки)

Время на прочтение12 мин
Количество просмотров6.8K

В предыдущей части мы остановились на мысли, что минимизировать простой вспомогательных потоков нашего приложения можно, если заставить их самих получать себе задачи, не дожидаясь, пока их загрузит кто-то другой со стороны.

Но тут возникает две проблемы:

1. как эффективно доставить данные в обрабатывающий поток

2. как распределять задачи между активными потоками, чтобы ничего не пропустить, но и дважды не обработать

В этом нам как раз и помогут два рассматриваемых в этой статье концепта работы с многопоточностью: разделяемая (shared) память и потокобезопасные (thread-safe, Atomics) операции над ней.

Читать далее
Всего голосов 21: ↑21 и ↓0+21
Комментарии7

Приручаем многопоточность в Node.js (часть 2/5: очередь, каналы и координатор)

Время на прочтение16 мин
Количество просмотров8.8K

В первой части статьи мы остановились на моменте, когда с помощью распределения задач между потоками по алгоритму Round-robin мы добились-таки ускорения работы приложения за счет многопоточности.

Но вот неприятность: такой алгоритм очень неравномерно нагружает потоки и не полностью утилизирует их возможности - пока кто-то простаивает, другой уже копит очередь. Как это можно обойти?

Читать далее
Всего голосов 14: ↑14 и ↓0+14
Комментарии8

Приручаем многопоточность в Node.js (часть 1/5: базовые концепты)

Время на прочтение8 мин
Количество просмотров21K

Продолжаем серию статей, посвященных разным прикладным концептуальным решениям, которые могут существенно "прокачать" производительность вашего Node.js-приложения.

В прошлой статье мы рассмотрели реализацию эффективной очереди на основе "эластичного" кольцевого буфера, а в этой попробуем разобраться с особенностями использования модуля Worker threads в Node.js - какие проблемы внедрения многопоточности будут нас ждать при попытках сделать код более производительным, и узнаем, как их можно обойти, применяя типовые концепты.

Начнем с достаточно типовой задачи: мы получаем некоторые сообщения, и нам их надо как-то обработать. В качестве тестового примера сгенерируем эти сообщения самостоятельно, и посмотрим, за какое минимальное время мы сможем вычислить SHA-256-хэш для каждого из них.

Читать далее
Всего голосов 21: ↑21 и ↓0+21
Комментарии5

Эффективная FIFO-обработка для Node.js и Chrome

Время на прочтение9 мин
Количество просмотров7.6K

"По классике" FIFO-очередь для обработки некоторого потока задач обычно реализуется в виде связанного списка элементов. Но для JavaScript такой подход нехорош - он требует либо создания "обвязки" над элементом очереди в виде дополнительного объекта, содержащего ссылки на сам элемент и указатель на следующий, либо превращения элемента в объект и расширения его таким же указателем.

В таких нагруженных системах, как коллектор нашего сервиса мониторинга PostgreSQL-серверов, создание и последующая подчистка Garbage Collector'ом подобных избыточных объектов и полей - непозволительная роскошь.

Но если внимательно посмотреть на эту схему, то можно заметить, что сами элементы очереди A, B, C линейно упорядочены. Так нельзя ли использовать в качестве очереди обычный массив с его .push() и .shift()?..

Насколько это будет эффективно, какие грабли встретятся на этом пути, и как их можно обойти - сегодня об этом.

Читать далее
Всего голосов 16: ↑16 и ↓0+16
Комментарии7

PostgreSQL Antipatterns: где скаляру в GiST место?

Время на прочтение3 мин
Количество просмотров3.2K

В PostgreSQL есть "волшебный" тип индекса GiST, который позволяет быстро искать разные сложные вещи - от интервалов до массивов и даже реализовывать полнотекстовый поиск.

Про его внутреннее устройство и возможности подробно рассказывал Егор Рогов, а я в статье "PostgreSQL Antipatterns: работаем с отрезками в «кровавом энтерпрайзе»" показал, как с помощью расширения btree_gist он позволяет решать типовые бизнес-задачи.

Одной из таких задач является поиск отрезков внутри сегмента со скалярным идентификатором. И если для btree очевидно, что поле с меньшей кардинальностью должно стоять в индексе раньше - индекс от этого и меньше и быстрее (см. "DBA: находим бесполезные индексы"), то так ли это однозначно для btree_gist?

Читать далее
Всего голосов 10: ↑10 и ↓0+10
Комментарии0

Self-hosted EXPLAIN: наглядно и безопасно

Время на прочтение2 мин
Количество просмотров7.9K

С момента первой же хабрапубликации о возможностях нашего сервиса визуализации планов запросов PostgreSQL explain.tensor.ru (а было это уже больше 2 лет назад) пользователи задавали резонный вопрос: "Все у вас круто, но у нас в запросах и планах есть коммерческая инфа, которую отправлять куда-то наружу низзя... Можно как-то ваш сервис развернуть на своей площадке?"

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

Читать далее
Всего голосов 32: ↑32 и ↓0+32
Комментарии9

SQL HowTo: наперегонки со временем

Время на прочтение2 мин
Количество просмотров9.3K

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

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

Читать далее
Всего голосов 11: ↑11 и ↓0+11
Комментарии2

PostgreSQL Antipatterns: куда крутить NULLS

Время на прочтение2 мин
Количество просмотров6.6K

Периодически приходится разбирать случаи внезапного промаха запроса мимо "вроде бы подходящего" индекса - а все дело оказывается в чуть-чуть не той сортировке.

Читать далее
Всего голосов 21: ↑21 и ↓0+21
Комментарии13

SQL HowTo: обход дерева иерархии «по курсору» через двойную рекурсию

Время на прочтение3 мин
Количество просмотров9.5K

В предыдущих статьях "PostgreSQL Antipatterns: навигация по реестру", "PostgreSQL 13: happy pagination WITH TIES" и "SQL HowTo: курсорный пейджинг с неподходящей сортировкой" я уже рассматривал проблемы навигации по данным, представленных в виде плоского реестра.

Но что если мы хотим выводить данные не простым "бесконечным списком", а в виде иерархической структуры с быстрой навигацией по узлам - например, обширный каталог товаров или меню ресторана, как это делает Presto - наш продукт для автоматизации заведений питания? Вот тут нам и придется что-то поизобретать...

Читать далее
Всего голосов 15: ↑15 и ↓0+15
Комментарии24

«Ленивый сахар» PostgreSQL

Время на прочтение7 мин
Количество просмотров43K

SQL - декларативный язык - то есть вы описываете "что" хотите получить, а СУБД сама решает, "как" именно она будет это делать. Некоторые из них при этом позволяют им "подсказывать", как именно лучше выполнять запрос, но PostgreSQL - нет.

Тем не менее, "синтаксический сахар" некоторых языковых конструкций позволяет не только писать меньше кода (учите матчасть!), но и добиться, что ваша база будет делать часть вычислений "лениво", только при фактической необходимости.

Читать далее
Всего голосов 42: ↑42 и ↓0+42
Комментарии15

PostgreSQL Antipatterns: когда мешает внешний ключ

Время на прочтение5 мин
Количество просмотров16K

Внешние ключи (foreign keys) - мощный и удобный механизм контроля логической целостности данных в базе. Но он бывает не только лишь полезен, и может неплохо пригрузить вашу БД.

Внимательный взгляд на план запроса поможет избежать многих проблем - как при чтении из базы, так и при вставке в нее.

Читать далее
Всего голосов 24: ↑24 и ↓0+24
Комментарии12

PostgreSQL Antipatterns: в этом плане кто-то лишний

Время на прочтение3 мин
Количество просмотров7.6K

Сегодня будет рассказ про избыточные группировки и сортировки в SQL-запросах - как они возникают, по каким признакам их можно потом вычислить и как избавиться от них.

Читать далее
Всего голосов 10: ↑10 и ↓0+10
Комментарии0

Информация

В рейтинге
66-й
Откуда
Ярославль, Ярославская обл., Россия
Работает в
Дата рождения
Зарегистрирован
Активность