• Вышел PostgreSQL 10
    +3
    Кстати, PostgresPro вроде имеет свой сертифицированный форк. А расскажите про Линтер, что за зверь такой? А то в интернетах про него внятных технических подробностей не нашёл при поверхностном поиске. И раз вы сказали, что сильная сторона pg — это mvcc, то что тогда у Линтера? Блокировщик?
  • Вышел PostgreSQL 10
    +1

    Ну понятно, что нормального мультимастера пока нет и раньше 12-13 версии pg его ждать глупо. По поводу костыльной реализации мультимастера на базе логической репликации здесь и сейчас… можете попробовать на двух серверах создать родительскую таблицу с двумя партициями. Ключом партицирования будет id сервера. На первом сервере при вставке в родительскую таблицу данные попадут в первую партицию, на втором сервере — во вторую. Первая партиция на втором сервере будет подписана на первую партицию на первом сервере. Вторая партиция на первом сервере будет подписана на вторую на втором. По факту такая конструкция может пережить сплит брейн за счёт того, что данные вносятся на каждом сервере в свою партицию и уникальность им обеспечит id сервера (поэтому конфликтов не возникает). Ну и делать такие вещи есть смысл не через нативное партицирование десятки, а через pathman. Но это так, теория, подобные костыли я не проверял.

  • Cила PostgreSQL
    0
    думаю, под «select в некоторых случаях может менять данные» подразумевается история в pg про обновление хинт битов при первом чтении вставленной строки. суть в том, что pg версионник, то есть под капотом в его таблицах лежат незакомиченные и удаленные строки, которые периодически чистит автовакуум. при выборе, какие строки убить, автовакуум ориентируется на хинт биты (они нужны еще для кучи разных вещей, не только для этого). когда вы начали транзакцию, но еще не закоммитили ее, строка все равно появляется таблице, а в хитн битах у нее пусто. как только транзакция коммитится, информация об этом замечательном факте попадает в clog. к сожалению, понять в момент коммита, в каких строках таблиц транзакция успела поменять данные проблемно, да и часть страничек может быть вытеснена из буферного кеша (а повторно считывать их дорого). поэтому в строках из закомиченной транзакции хинт биты остаются пустыми. а вот как только мы запросим через select одну из таких строк, pg проставит им хинт биты, что вызовет запись на диск при чтении данных. ну а если таких строк было много, то первое чтение может породить серьезную нагрузку на диск за счет вытеснение грязных страничек их общих буферов pg. это порой ставит в тупик не наступавших на эти грабли людей.
  • Подходы к версионированию изменений БД
    0
    Для PostgreSQL пользуюсь Pyrseas. Он снимает описание со схемы в виде yaml файла, который можно сравнить с любой базой и по разнице автоматически генерируется sql миграция. За счёт этого можно работать в параллельных ветках базы и нормально сливать изменения. Поддерживаются специфичные для PG вещи (вот марица поддерживаемых свойств).
  • Как наука о данных помогает развитию медицины. Лекция в Яндексе
    0
    Вы не можете записаться на удобное вам время просто потому, что денег нет. ТФОМС раз в год выдаёт план задание — обязательство каждому медучреждения оплатить N медицинских услуг, не больше и не меньше. И медучреждение обязано их сделать ровно столько, сколько выдал в виде плана ТФОМС. Меньше сделаешь — урежут в следующем году план, больше — не заплатят. Проблема в том, что ТФОМС обязуется оплатить количество услуг в несколько раз меньшее, чем реально нужно населению. Медучреждение планирует этот минимум помесячно, чтобы не выполнить весь годовой план за пару месяцев. Услуг не хватает, а что есть разлетается как горячие пирожки. Денег на ОМС медицину у государства нет, поэтому развивается только платный сегмент. А с учётом полной импортозависимости по реагентам, расходникам и оборудованию, а так же с учётом курса, платная медицина будет только дорожать.
  • Чек-лист по выживанию сайта
    0
    Приношу извинения, автор не вы — пятница вечер))
    Что вы подразумеваете под «хранящиеся отдельно»? Если речь про кеши, то аргумент трудно принять. Если про посчитанные агрегаты, то это не всегда применимо — для разных пользователей будут свои значения агрегатов в каждый момент времени, их нет смысла считать заранее.
  • Чек-лист по выживанию сайта
    0
    У вас в статье не шла речь про веб приложение, вы давали общие рекомендации. Я же вам привёл данные из работающей системы медицинских заказов на целый край. И это не редкий аналитический запрос, а типовая проверка для заказа направления между медицинскими учреждениями. Такие данные нельзя хранить отдельно и обновлять, они должны быть актуальны на любой момент времени. И они как то держатся настолько сложными и отлично работают в продакшене. Если вы пишите практики для простых веб приложений, то и указывайте об этом. Реальные промышленные системы обычно на порядок сложнее.
  • Чек-лист по выживанию сайта
    +2
    Могу сказать, что у меня идут запросы с агрегациями по соединениям таблиц, в каждой из которых около миллиона записей. Соединяются от трех до пяти таких таблиц. Соединение идёт по покрывающим индексам и почти не трогает сами таблицы, то речь менее чем о сотне мс. Суть в том, что агрерация идёт в pipeline mode по покрывающим индексам и на клиент уходит компактная свертка результатов в пару сотен строк. Если же делать по-вашему, то нужно выкачать несколько миллионов строк с дисков, отослать их на другой сервер и там повернуть ту же самую свертку в памяти в компактную таблицу, но без кучи оптимизаций по работе с общими буферами PG и буферами ОС. Если хотите, напишите предложение по тесту, я его прогоню по-своему и по-вашему.
  • Чек-лист по выживанию сайта
    +7
    Простите, я правильно понимаю, что вы предлагаете вытащить данные из 10 таблиц, передать их по сети, реализовать через сторонние библиотеки на другом сервере хеш соединение в памяти… и утверждаете, что это быстрее, чем нативная реализация СУБД? Я пользуюсь PG и могу точно сказать, что соединения в базе быстрее. И слабо верю, что в MySQL оно работает сильно хуже
  • Клинический анализ крови: от светового микроскопа к гематологическим анализаторам
    0
    Чертова автозамена на телефоне, это все она!
  • Клинический анализ крови: от светового микроскопа к гематологическим анализаторам
    0
    Про промывку не скажу, я ж программист) Но зная врача, которая за этот прибор отвечает, там все строго по регламенту производителя.
    Пробирки у нас вакуэт, забор крови под боком и раз в не-помню-сколько минут оттуда приносят новую партию и ставят на борт — поэтому в холодильнике нужды нет. Сколь я знаю, даже хорошие пробирки, нормальные медсестры и близкий забор крови не спасают от появления сгустков. Плюс есть кровь по проекту централизованной лаборатории, которую у нас на оленях везут. Да, тоже вакуэт пробирки, но там никаких гарантий по качеству забора и транспортировки.
  • Клинический анализ крови: от светового микроскопа к гематологическим анализаторам
    0
    Я могу сказать, что в КДЦ, где я работаю, мазки смотрят только вручную и ни о какой замене этого процесса DxH800 и речи не идёт. Мазки смотрят, когда кровь у человека сильно плохая и там нужно внимательно разбираться, что происходит. Такие вещи прибору не доверяют (плюс допускаю, он не все показатели может в мазке посчитать — это надо у гематологов наших спрашивать)
  • Клинический анализ крови: от светового микроскопа к гематологическим анализаторам
    0
    Кстати, если вас могли испугать интерфейсы re-232, то это не страшно. Мы в лаборатории поставили rs232-to-ethernet конвекторы и пробросили виртуальные com порты на сервер с драйверами ЛИС. Это позволило не держать лишний компьютер с rs-232 рядом с анализаторами и экономит место в лаборатории.
  • Клинический анализ крови: от светового микроскопа к гематологическим анализаторам
    0
    А вообще DxH800 имеет отличную пропускуную способность, кучу показателей ОАК… но не имеет нормальных фильтров от сгустков крови в пробирках. В результате у нас сервисное обслуживание не вылазит с этих приборов. Со старыми МЕКами таких проблем никогда не было.
  • Клинический анализ крови: от светового микроскопа к гематологическим анализаторам
    0
    У нас в лаборатории стоят два таких. На борту прибора винда, экспорт по описанному в документации формату через интерфейс rs-232 (данный интерфейс стандарт в лабораторной диагностике). Так что драйвер, который будет отвечать за двусторонний обмен с лабораторной информационной системой (ЛИС) можно написать под любую платформу. Обмен может быть двусторонний или односторонний. В двустороннем получив пробирку на борт прибор запрашивает у ЛИС перечень показателей общего анализа крови и делает только их, а потом отправляет в ЛИС результаты. В одностороннем, получив на борт пробирку, прибор сразу делает все показатели, а потом отправляет результаты в ЛИС. Результаты хранятся в ЛИС, но какая-то база с результатами в приборе есть (возможность посмотреть через прибор, что делали сегодня/на прошлой неделе/в прошлом месяце должна быть). Не была повода смотреть, какая именно, но скорее всего или MSSQL Express, или Firebird.
  • Ускоряем восстановление бэкапов в PostgreSQL
    0
    Как вариант, можно настроить в привилигерованном lxc контейнере реплику и использовать ее в качестве образа для легковесных overlayfs контейнеров. То есть мастер транслирует wal логи на lxc реплику. Когда мы хотим себе полигон, просто делаем lxc-copy с типом overlayfs (легковесный снимок основного lxc контейнера, который пишет только разность относительно замороженного слоя), переводим postgresql overlayfs копии в боевой режим и экспериментируем на здоровье. Должно происходить мгновенно. Была статья на хабре, где парень что-то похожее на эту схему делал, только на btrfs
  • Топ инструментов разработки для PostgreSQL
    0
    Для версионирования или сравнения схем использую Pyrseas. Очень хорошая штука, кстати.
  • Почему много JOIN в запросе это плохо или не мешайте оптимизатору
    +2
    Хорошо, спрошу максимально прямо — о чем эта статья и что из нееследует вынести после прочтения?
  • Почему много JOIN в запросе это плохо или не мешайте оптимизатору
    +2
    Понимаете, просто само название статьи и начала абзацев вроде
    Я бы хотел рассмотреть почему же SQL Server так долго строит план запроса.
    Давайте поговорим о порядке соединения таблиц подробнее

    настраивают на то, что на примере запроса из начала статьи будет разобран алгоритм построения плана и дана общая теория по специфике работы планировщика MS SQL. А закончится статья тем, что автор победил проблему с учётом вышеописанных знаний. По итогу же имеем «Вот запрос, нагенерированный 1С на 20 таблиц с повторами. Он строится иногда долго. Почему? Много таблиц в соединении плохо, так как эн-факториал. Вывод — не делайте много таблиц и уважайте планировщик». Ну такому уровню статей не место на Хабре, простите.
  • Почему много JOIN в запросе это плохо или не мешайте оптимизатору
    +1
    Я так и не понял из статьи, как именно MS SQL находит баланс между стоимостью плана и лимитом по времени перебора. N! вариантов — это хорошо для объяснения на пальцах, но вряд ли именно так все работает. У того же PostgreSQL помимо стандартного планировщика запросов есть ещё модуль генетической оптимизации. На последнем pgconf показывали модуль адаптивной оптимизации, который учитывал предыдущий опыт построения планов по схожим запросам. Наверняка в MS SQL все не менее наворечено и можно тоже что-то понастраивать с вычислением стоимости планов на большом количестве соединений. А просто сказать, что когда много таблиц, то планировщик начинает работать не очень… не информативно.
  • Релиз DataGrip 2017.1
    +2
    Хотелось бы для PostgreSQL больше поддержки нативных объектов. Сейчас нет ни оберток над внешними данными (внешние таблицы, схемы и сервера), ни типов, ни расширений, ни объектов полнотекстового поиска (словари, парсеры, шаблоны), ни правил. К сожалению, как бы я ни желал перейти с PgAdmin на DataGrip, пока функционал последнего не позволяет это сделать…
  • Редкий SQL
    0
    Мой опыт PostgreSQL подсказывает никогда не использовать конструкцию NOT IN, это самый медленный вариант из возможных — все жду, когда планировщик PostgreSQL научится с ним нормально работать. Обычно исключение строк реализуется или через EXCEPT, или через LEFT JOIN… WHERE id IS NULL. Но EXCEPT из этих вариантов самый производительный.
  • Как писать кривые запросы с неоптимальным планом и заставить задуматься СУБД
    +1
    А вот теперь суть истории стала понятна и статья обрела смысл) Да, безусловно, использовать внутри рекурсивного запроса конструкцию with для вычисления следующего шага нельзя, это обычно фатально для производительности. Я тоже так стрелял себе в ногу…
    Вообще вы подняли хорошую тему — надо бы собрать набор паттернов и антипаттернов в sql и написать большую статью, которая дополнялась бы по мере обсуждения в комментариях. Не хотите попробовать?;)
  • Как писать кривые запросы с неоптимальным планом и заставить задуматься СУБД
    0
    По факту вся статья сводится к простому правилу — минимизируйте количество строк и столбцов на каждом этапе запроса для увеличения производительности.

    По поводу первой части с with… Проблема была не в cte, а в некорректно переписанном запросе, который не использовал условие where product_id = 1234. Ещё бы он не работал медленнее. Зачем вы смущаете юных падованов, связывая замедление с конструкцией with?)
    Опять же, аргумент вида
    Если айдишних получается, например, в ходе рекурсивного запроса, то в WITH такое условие не утащишь и идея с разделением запроса на куски будет безбожно тормозить

    далёк от истины. Ничто не мешает положить результат рекурсивного запроса в виде единственного айдишника в cte, а потом написать
    where product_id = (select id from recursive_with)
    


    Касаемо красивой визуализации explain analyze — лично я предпочитаю построение в pgAdmin: толщина связей в отображении плана запроса очень чётко указывают на проблему производительности.
  • Оптимизация одного запроса с GROUP BY в PostgreSQL
    0
    Сколь я помню у PosgresPro есть возможность при создании индекса помещать в его листья дополнительные поля, чтобы не обращаться к таблице. Параметр including, если память не изменяет. А вообще используйте вариант genew с поиском по индексу без обращения к таблице (кстати, вам на самом деле нужен только один составной индекс, а не целых три!). Этот вариант лучше массива залитого gin — в массиве вы теряете согласованность данных на внешних ключах. Кстати, во внешних ключах правильнее использовать on update cascade, чем no action — понятно, что первичные ключи не обновляют, но концептуально… А в запросе вместо distinct можно попробовать group by, он на прежних версиях меньше ошибался.
  • SQL: пара приемов в SELECT-запросах
    0
    Курсоры — это медленно и очень плохая практика в sql. Ну и да, вы смотрели план выполнения запроса в этом именованном алгоритме?
  • SQL: пара приемов в SELECT-запросах
    +1
    Забавы ради попробовал решить, не подглядывая в ваш вариант (PostgreSQL).
    Создаем таблицу с данными (данные неупорядоченные)
    create table weather(time timestamp, clear boolean);
    
    insert into weather(time, clear)
    select generate_series(
      '2000-01-01'::timestamp, 
      '2009-01-01'::timestamp, 
      random() * 7 * '1 day'::interval
    ) as time,
    random() > 0.5 as clear order by random();
    

    Находим интервалы солнечных дней (начало, конец и длина), упорядочиваем по длине и выбираем 20.
      with ordered_weather as (select * from weather order by time),
      nasty as (
        select row_number() over() as gap_group, time, clear from ordered_weather where not clear
      ),
      gaps as (
        select row_number() over(), b.gap_group, a.time, a.clear from ordered_weather a
        left join nasty b using (time, clear)
      ),
      limited_gaps as (
        select 0 as row_number, 0 as gap_group, 
        (select min(time) - '1 day'::interval from weather) as time, false as clear
        union all
        select * from gaps
        union all
        select (select max(row_number) + 1 from gaps), (select max(gap_group) + 1 from gaps), 
        null::timestamp, false
      )
      select c.time as clear_start, d.time as clear_stop, (d.time - c.time) as clear_interval 
      from limited_gaps a
      left join (
        select row_number, gap_group + 1 as gap_group from limited_gaps where gap_group is not null
      ) b using(gap_group)
      join limited_gaps c on c.row_number = coalesce(b.row_number,0) + 1
      join limited_gaps d on d.row_number = a.row_number - 1
      where a.gap_group is not null and (a.row_number - coalesce(b.row_number,0) > 1)
      order by (d.time - c.time) desc limit 20;
    
  • Техника безопасности при работе с PostgreSQL
    0
    Я внес замечания в статью по поводу with, deferrable и set autocommit off. Спасибо большое за замечания и советы.
  • Техника безопасности при работе с PostgreSQL
    0
    Поправил, это и правда было написано плохим стилем.
  • Техника безопасности при работе с PostgreSQL
    0
    Кроме того создание инкрементального бекапа при помощи braman это отдельная боль (если у вас БД больше 100 гигов)

    А можно поподробнее про подводные камни на 100 ГБ? У меня БД на 60 ГБ, хочу узнать, к чему готовиться через пару лет.
  • Техника безопасности при работе с PostgreSQL
    0
    Если количество клиентов гарантированно останется небольшим (десяток-другой) и увеличиваться никогда не будет, то да. Главное, не ошибиться.
  • Техника безопасности при работе с PostgreSQL
    0
    Я и правда не очень четко выразился. Речь о том, что создавать для каждого пользователя приложения своего пользователя в БД — очень плохая практика. При дальнейшем росте нагрузок (а они растут внезапно и незапланированно) это обернется невозможностью использовать пулы соединений к базе.
  • Техника безопасности при работе с PostgreSQL
    0
    Вы получите согласованность на конец выполнения транзакции и (опционально) на любой момент внутри ее. Это позволяет упростить жизнь при вставке данных одной транзакцией в разные таблицы, где из-за внешних ключей нужно иначе было бы учитывать порядок вставки. Плюс это иногда удобно при импорте данных через insert.
  • Техника безопасности при работе с PostgreSQL
    +2
    Это, скорее, правило хорошего тона. Но теоретически, можно получить проблемы конфликта имен при установке расширений, которые используют схему public для своих функций. Маловероятно, но возможно.
  • Техника безопасности при работе с PostgreSQL
    +3
    И не просто наступал, но и героически преодолевал последствия. До сих пор вздрагиваю.
  • Ограничения (сonstraints) PostgreSQL: exclude, частичный unique, отложенные ограничения и др
    0
    Посмотрел на теги внизу и нашёл родственную душу — я всегда делаю такую же ошибку в написании слова deferrable ;) и только написав вспоминаю, что где-то был капкан.
  • Вы не любите триггеры?
    0
    Проблема в том, что использовать базу для аутентификации пользователей — плохая идея, этим должен заниматься сервер. Как я понял, вы решили схитрить и просто прокидывать пользователя к БД, а она пусть штатными средствами и разбирается кто есть кто и что ему можно. Это неправильная архитектура по причине отсутствия возможности для маштабируемости. Если у вас резко увеличится количество пользователей, база ляжет. И никакие балансировщики нагрузки БД вам не помогут, так как каждый пользователь будет со своим подключением, и их нельзя будет собрать в единый пул.
    Вам не нужно поддерживать соответствие между пользователями в БД и на сервере. В простейшем случае в базе из пользователей будут владелец базы и пользователь для пула коннектов, под которым все ходят. У этого пользователя не будет прав на таблицы, только на выполнение функций с security definer. В каждой транзакции сервер должен выставлять
    begin;
    select set_config('ваша_переменная_пользователя_из_pg_config', 'пользователь_на_сервере', false);
    select func(...);
    commit;
    

    Перед выполнением каждой функции в ней должна быть проверка на то, что имя пользователя, содержащееся в глобальной переменной на уровне данной транзакции, разрешено для запрашиваемой функции. Это делается через
    select current_setting('ваша_переменная_пользователя_из_pg_config') into username;
    

    А дальше мы и смотрим, может ли данный username использовать вызванную функцию. Но эта проверка должна быть на уровне некой дополнительной функции, а не через пользователей PostgreSQL.
  • Вы не любите триггеры?
    0
    Базы данных держат сотни подключений, а не тысячи, как web сервера. И каждое простаивающее подключение съедает ресурсы. Именно поэтому никто взаимооднозначно не транслирует клиентов через сервер в базу, а заворачивают кучу пользователей в один пул. Иначе база не потянет. Поэтому штатными средствами acl базы вы сможете раздать права на выполнение функций только учеткам, которые используются в пуле. Не штатными — можно использовать GUC (в случае PostgreSQL), выставляя на сервере в каждой транзакции имя пользователя через set_config. А в функциях вытаскивать из глобальной переменной имя пользователя и делать проверку.