Хороший вариант кстати, кажется такой не рассматривали.
Рассматривали похожий, но еще более простой - вообще не добавлять поле result_code а сделать партицирование по выражению result == 'Автоответчик' и потом методом LIST true положить в одну партицию, false в другую. Но в таком варианте возможна проблема в случае если вдруг у нас кроме Автоответчика появится какой-то еще result который относится к not-important. Тогда пришлось бы менять выражение для ключа партицирования.
Ваш вариант такой проблемы не имеет и нам бы подошёл, да.
вы сначала из твоей системы отдавали по api данные в другую, а уже оттуда данные попадали в dwh
Не так. По апи данные мы отдавали системе которая к DWH отношения не имеет. DWH же данные забирали через слот репликации из нашей базы. Не через SQL-запросы к нашим таблицам, а через логическую репликацию они получали поток строк конкретных таблиц конкретной структуры. Именно поэтому вьюхи были неприменимы, на изменения во вьюхе же невозможно подписаться через репликацию.
Причем Вы могли прямо в текущей базе сделать нормальную модель и отдать потребителям view
Выше писал, что насколько мне известно, DWH через слот репликации данные забирали, не уверен что вьюхи тут бы помогли.
Это у вас НЕДОСТАТОЧНАЯ нормализация данных, как и в таблице коммуникантов. Недостаточная нормализация как раз увеличивает объемы, ухудшает возможности оптимизации с помощью индексов и приводит к конфликтам рассогласованности данных
Недостаточная в том плане, что коммуниканты дублируются и каждой коммуникации свой отдельных коммуникант - это да. Под денормализацией я имел в виду то, что наша модель из пяти таблиц нормально могла бы уложиться в одну. И было бы нужно в 5 раз меньше индексов и индекс-сканов.
Насчёт корректности термина "нормализация" вас понял, тут спорить не буду.
То есть во время тесты вы должны были в 6 раз увеличить объемы данных для тестирования
И RPS и объём БД на тестах были кратно увеличены. Ошибка была в том что при этом абсолютно не воспроизводилась ситуация, в которой на одном clientId было много активностей. Вместо этого было генерилось много клиентов с одной активностью, что абсолютно не соответствовало ситуации на проде.
почему вы продолжали использовать include, а не вписали проекции только тех значений что нужны конкретно для dwh? Вряд ли там все поля таблицы используются
.NET-сервис отдавал данные не для DWH, а для другой системы. Там отдавались нужные проекции (в статье просто не стал загромождать код этими деталями). Но они к слову тоже довольно развесистые были, там почти все поля.
почему не пытались сделать покрывающие индексы и свести все к index only scan?
Покрывающие индексы могут быть полезны если нужно читать пару полей. Когда почти вся таблица нужно, то смысла почти всю таблицу дублировать в индексах уже нет.
почему не применили filtered indexes
Т.к. всё равно прорабатывали партицированием по дате и всё делали в сжатые сроки - Банально об этом не подумали в тот момент, т.к. прорабатывали партицирование по дате и зациклились немного на идее партицирования как таковой. А так идея отличная. Частичные индексы можно было бы использовать вместо партицирования вторым уровнем по result_code, всё верно.
возможно стоило попробовать перенести op_data в jsonb поле в самой activity, тогда и читать пришлось бы меньше
Согласен, будь моя воля, я бы вообще всё в одной таблице сделал. Но тогда переезд на другую схему был для нас недоступной опцией, в статье я об этом упоминал. К слову, сейчас рассматривается вариант переезда этого сервиса на Cassandra с одной таблицей как раз т.к. приближаемся к 1 ТБ, а постгресовые инстансы больше 1 ТБ у нас очень не любят.
Мы не выносили. Хотя в этом есть смысл если хочется сэкономить на железе и под старые партиции, к которым очень мало запросов, использовать более медленные и дешёвые диски.
Если быть точнее, мы пускали не совсем сервис, а некий платформенный инструмент. И не совсем в таблицы, а скорее в слот репликации. И из-за этого фокус с вьюхами вряд ли бы получился, через слот репликации не получилось бы их изменения получать. Здесь на 100% не ручаюсь, очень глубоко я в устройство этого инструмента не погружался, но кажется ситуация была такая.
К счастью это всё уже в прошлом, теперь отправка данных в DWH делается другим, намного более гибким и независимым от БД способом.
На 99м перцентиле новый вариант получения записей давал ускорение на несколько десятков миллисекунд. Учитывая, что на начало сбоя время работы достигало несколько секунд - этого явно было бы недостаточно.
Самый хороший буст дала ещё более простая мера - отфильтровывание автоответчиков (в статье об этом сказано). Дальнейшие работы по партицированию были нужны для стабилизации размеров активно используемых индексов по мере роста базы и для упрощения обслуживания (например, архивации старых записей)
Простыми словами, поколения нужны для оптимизации, что бы каждый раз не перебирать всю кучу и не тратить на это все ресурсы.
Это не совсем верно. Для определения недостижимых объектов куча всё равно "перебирается" вся целиком, т.к. осуществляется построение и обход графа всех объектов независимо от поколений.
А вот последующие этапы сборки мусора (освобождение памяти, дефрагментация) уже оптимизируются за счёт механизм поколений т.к. выполняются не на всей куче, а на поколении.
> этот код возвращает err в рантайме, а не ошибку компиляции:
Может я что-то не понимаю, но разве в каком-то языке возможно на подобное получать ошибку компиляции, а не ошибку в рантайме? Ведь мы же на этапе компиляции не знаем, что введёт пользователь и окажется ли введённая им строка целым числом.
В комментах ещё не упоминали такой стиль электронной музыки, как Liquid DnB. В последнее время мне нравится включать его фоном на небольшой громкости, когда пишу код. Такая музыка не отвлекает от работы, в то же время она достаточно энергичная и помогает таким образом не сбавлять рабочий темп.
Ну а ещё нравится во время работы слушать уже упомянутые здесь пост рок и транс, реже — тяжёлый рок и металл.
Ну тут, насколько я понимаю, проблема не столько в php-pm, сколько в приложениях, которые пытаются под ним запускать, но которые изначально создавались для другой («умирающей») модели выполнения.
Имеет ли Zend какие-либо преимущества по сравнению с Symfony для больших и Enterprise проектов? Просто кажется, что на этом поле как раз Symfony стал стандартом де-факто, а Zend как-то не виден и не слышен.
Хороший вариант кстати, кажется такой не рассматривали.
Рассматривали похожий, но еще более простой - вообще не добавлять поле result_code а сделать партицирование по выражению
result == 'Автоответчик'и потом методом LIST true положить в одну партицию, false в другую. Но в таком варианте возможна проблема в случае если вдруг у нас кроме Автоответчика появится какой-то еще result который относится к not-important. Тогда пришлось бы менять выражение для ключа партицирования.Ваш вариант такой проблемы не имеет и нам бы подошёл, да.
Не так. По апи данные мы отдавали системе которая к DWH отношения не имеет. DWH же данные забирали через слот репликации из нашей базы. Не через SQL-запросы к нашим таблицам, а через логическую репликацию они получали поток строк конкретных таблиц конкретной структуры. Именно поэтому вьюхи были неприменимы, на изменения во вьюхе же невозможно подписаться через репликацию.
DWH подписывались на слот репликации и получали изменения для определенных таблиц определенной структуры
Выше писал, что насколько мне известно, DWH через слот репликации данные забирали, не уверен что вьюхи тут бы помогли.
Недостаточная в том плане, что коммуниканты дублируются и каждой коммуникации свой отдельных коммуникант - это да.
Под денормализацией я имел в виду то, что наша модель из пяти таблиц нормально могла бы уложиться в одну. И было бы нужно в 5 раз меньше индексов и индекс-сканов.
Насчёт корректности термина "нормализация" вас понял, тут спорить не буду.
И RPS и объём БД на тестах были кратно увеличены. Ошибка была в том что при этом абсолютно не воспроизводилась ситуация, в которой на одном clientId было много активностей. Вместо этого было генерилось много клиентов с одной активностью, что абсолютно не соответствовало ситуации на проде.
.NET-сервис отдавал данные не для DWH, а для другой системы. Там отдавались нужные проекции (в статье просто не стал загромождать код этими деталями). Но они к слову тоже довольно развесистые были, там почти все поля.
Покрывающие индексы могут быть полезны если нужно читать пару полей. Когда почти вся таблица нужно, то смысла почти всю таблицу дублировать в индексах уже нет.
Т.к. всё равно прорабатывали партицированием по дате и всё делали в сжатые сроки - Банально об этом не подумали в тот момент, т.к. прорабатывали партицирование по дате и зациклились немного на идее партицирования как таковой. А так идея отличная. Частичные индексы можно было бы использовать вместо партицирования вторым уровнем по result_code, всё верно.
Согласен, будь моя воля, я бы вообще всё в одной таблице сделал. Но тогда переезд на другую схему был для нас недоступной опцией, в статье я об этом упоминал. К слову, сейчас рассматривается вариант переезда этого сервиса на Cassandra с одной таблицей как раз т.к. приближаемся к 1 ТБ, а постгресовые инстансы больше 1 ТБ у нас очень не любят.
Мы не выносили. Хотя в этом есть смысл если хочется сэкономить на железе и под старые партиции, к которым очень мало запросов, использовать более медленные и дешёвые диски.
Если быть точнее, мы пускали не совсем сервис, а некий платформенный инструмент. И не совсем в таблицы, а скорее в слот репликации. И из-за этого фокус с вьюхами вряд ли бы получился, через слот репликации не получилось бы их изменения получать. Здесь на 100% не ручаюсь, очень глубоко я в устройство этого инструмента не погружался, но кажется ситуация была такая.
К счастью это всё уже в прошлом, теперь отправка данных в DWH делается другим, намного более гибким и независимым от БД способом.
На 99м перцентиле новый вариант получения записей давал ускорение на несколько десятков миллисекунд. Учитывая, что на начало сбоя время работы достигало несколько секунд - этого явно было бы недостаточно.
Самый хороший буст дала ещё более простая мера - отфильтровывание автоответчиков (в статье об этом сказано). Дальнейшие работы по партицированию были нужны для стабилизации размеров активно используемых индексов по мере роста базы и для упрощения обслуживания (например, архивации старых записей)
Да, вы правы, как-то вылетел из головы у меня механизм card table.
Это не совсем верно. Для определения недостижимых объектов куча всё равно "перебирается" вся целиком, т.к. осуществляется построение и обход графа всех объектов независимо от поколений.
А вот последующие этапы сборки мусора (освобождение памяти, дефрагментация) уже оптимизируются за счёт механизм поколений т.к. выполняются не на всей куче, а на поколении.
> этот код возвращает err в рантайме, а не ошибку компиляции:
Может я что-то не понимаю, но разве в каком-то языке возможно на подобное получать ошибку компиляции, а не ошибку в рантайме? Ведь мы же на этапе компиляции не знаем, что введёт пользователь и окажется ли введённая им строка целым числом.
Blazor — это вроде как WebAssembly. В JS он не превращается ни на каком этапе, насколько я понимаю.
По-моему полноценную поддержку ES-модулей в node.js пока ещё так и не завезли.
Ну а ещё нравится во время работы слушать уже упомянутые здесь пост рок и транс, реже — тяжёлый рок и металл.
Попробуйте DBeaver. Бесплатный, поддерживает разные СУБД.