Ответы пользователя по тегу PostgreSQL
  • Как извлечь данные из JSON?

    Melkij
    @Melkij
    PostgreSQL DBA
    Если не нужен join со значениями, а только фильтр - то
    where array(select (j->>'category_id')::int from jsonb_array_elements(data->'items') j) && array[1,3,5];

    Можно загнать подзапрос с построением массива в immutable хранимку и повесить по ней gin или gist индекс.
    Ответ написан
    Комментировать
  • Как лучше сделать поиск по json ячейке?

    Melkij
    @Melkij
    PostgreSQL DBA
    Смотрим операторы: https://www.postgresql.org/docs/current/static/fun...
    Печально, прямого оператора как && overlap у массивов нет.
    ?| text[] Do any of these array strings exist as top-level keys?

    Зато тот вполне подходит. Значит, заменить json на jsonb затем запрос будет
    select * from t where jsonbfield ?| array['0', '5', '7']::text[];

    Если на входе удобен именно json массив, а не pg массив, то относительно просто переписывается одно в другое
    select * from t where jsonbfield ?| (select array_agg(t) from json_array_elements_text('["0","5","7"]') t);


    gin и gist индексы оператор ?| могут обрабатывать.
    Ответ написан
    Комментировать
  • Псевдо-персистентное соединение в PHP, возможно ли?

    Melkij
    @Melkij
    PostgreSQL DBA
    Используйте pgbouncer.
    Лучше всего в режиме transaction пула. Тогда backend postgresql будет выдаваться соединениям от приложения только на время выполнения транзакции. Что позволяет и очень эффективно утилизировать лишь небольшое число процессов postgresql и сохранить возможность транзакционной работы. В режиме транзакций не работают prepared statements, но PDO их и так эмулирует, так что проблемой это не является.

    pgbouncer легко держит тысячи открытых соединений с приложением, легко их открывает и закрывает, развлечения начинаются при попытке прокачать через баунсер с гигабит трафика (и обходится банально запуском второго баунсера тут же на другом порту). Обычно размещается на машине непосредственно с базой на 6432 порту.
    И вообще-то является фактическим стандартом для инсталляций postgresql.
    Ответ написан
    1 комментарий
  • Автоинкремент в INSERT INTO ... ON CONFLICT?

    Melkij
    @Melkij
    PostgreSQL DBA
    Никак. Работает как задумано.

    И уже при вставке идет разрыв в id.

    sequence не гарантирует неразрывность. И последовательность значений тоже не гарантирует.
    Гарантирует только уникальность значений.
    Ответ написан
    7 комментариев
  • Как правильно делать бекапы базы Postgresql на продашн сервере?

    Melkij
    @Melkij
    PostgreSQL DBA
    Зависит от:
    0) какой промежуток времени вам допустимо потерять при восстановлении
    1) сколько места вы можете выделить для хранения бекапов
    2) какой запас времени вы хотите сохранять для возможности восстановить данные когда-то из более далёкого прошлого

    Может, на мыло тоже отправлять на всякий случай?

    Как через почту пропихнуть даже мелкие бекапы в десяток гигабайт?
    Или вы про совсем крошечные базы спрашиваете?

    Шифровать или нет - зависит от требований к безопасности и оценке риска в случае disaster recovery не восстановить ключ шифрования.

    Для хорошего point in time recovery - pg_basebackup + pg_receivexlog (archive_command только если уверены, что можете её сделать нормально). Или что-то, работающее поверх них.
    Отдельный случай pitr с хранением в амазоне - см. вполне внятный wal-e
    Если pitr не обязателен, то pg_dump делать. Да, лучше архивировать, сжимаются дампы весьма неплохо.

    Например, политика бекапа из практики: ежедневный pg_dumpall, хранятся за 1 число каждого месяца на протяжении года плюс 8 дней предыдущих ежедневных.

    Что-то ещё - регулярно пробовать восстановить и запустить базу из бекапа.
    Ответ написан
  • Как при создании нового кластера postgres указать иное расположение хранения баз?

    Melkij
    @Melkij
    PostgreSQL DBA
    Для начала немного терминологии, чтобы явно говорить на одном языке.
    Кластер postgresql - это один запущенный postgres.
    Один кластер может содержать несколько именованных баз данных, но все они обслуживаются одним запущенным postgres.
    На физической машине кластеров postgres может быть несколько.

    А теперь - что вы хотите сделать?
    * перенести директорию базы в другое место. Остановить базу, скопировать rsync'ом datadir куда надо, на старом месте сделать симлинк (datadir в конфиге в этом случае даже не надо править, если поправить пути в конфиге - то не обязателен симлинк)
    * оставить одни БД в дефолтном месте, а некоторые другие - в другом, но под управлением одного кластера. Вам необходимо сделать tablespace и использовать его. При create database можно указать tablespace, который и будет считаться по-умолчанию для всех объектов этой базы (но переопределить его можно для каждого объекта)
    * запустить отдельный кластер. В одно и то же место вы две базы просто не вставите. Соответствующий, и обычно обязательный, параметр в initdb плюс указать datadir в конфиге или строке запуска базы (зависит от того, как будет запускаться база и где лежать ещё конфиг). А для весьма приятного враппера в debian и ubuntu pg_createcluster параметр --datadir так же есть сразу

    см. также Как правильно изменить месторасположение базы postgresql-9.2.18.rl7?
    Ответ написан
    1 комментарий
  • Как скопировать запросы,которые делает программа к Postgres sql?

    Melkij
    @Melkij
    PostgreSQL DBA
    Помимо log_statement = 'all' можно выставить настройку log_min_duration_statement в 0 - она тоже может логировать все запросы.

    Если запросов через базу проходит много не только от необходимой программы, то и log_statement и log_min_duration_statement возможно выставить только для пользователя, от имени котрого программа выполняет запросы. Например,
    alter user melkij set log_min_duration_statement = 0;
    Ответ написан
    1 комментарий
  • Какие книги прочитать по лучшим практикам проектирования БД?

    Melkij
    @Melkij
    PostgreSQL DBA
    Bill Karwin SQL Antipatterns
    В общем-то, в духе рефакторинга как раз: как делают часто неправильно, почему это плохо (но когда и адекватно для задачи) и как сделать лучше.
    Ответ написан
    1 комментарий
  • Как найти вывести список всех не найденных значений из массива?

    Melkij
    @Melkij
    PostgreSQL DBA
    select children.code is null as is_not_found, /*another children data is null too*/ 
    from unnest(array[...]) as code 
    left join children using(code)
    Ответ написан
    Комментировать
  • Как сделать временную таблицу с одинаковыми данными?

    Melkij
    @Melkij
    PostgreSQL DBA
    небольшая ремарка №3: а нафига вам вообще cross join понадобился?
    SELECT 'Economy' FROM generate_series(1,10);
    Ответ написан
    1 комментарий
  • Как правильно изменить месторасположение базы postgresql-9.2.18.rl7?

    Melkij
    @Melkij
    PostgreSQL DBA
    С большим даунтаймом, зато целиком на новый диск:
    Потушить базу, скопировать PGDATA (data_directory в конфиге) в новое место, заменить data_directory в конфиге на новое место, запустить базу.
    Можно, кстати, не менять data_directory, а сделать симлинк. Postgresql не против по симлинкам сходить за своими данными.

    С небольшим даунтаймом, зато с чуть большим числом телодвижений:
    через pg_basebackup сделать копию в новом месте, запустить там второй инстанс постреса с репликой. Когда реплика догонит мастер, потушить мастер (сделав checkpoint), потушить реплику (тоже с чекпоинтом), заменить data_directory в конфиге на новое место, запустить базу.

    Без даунтайма:
    инициализировать второй диск как tablespace, перенести на этот tablespace что мешается на основном (pg_repack попробуйте, емнип умеет без пишущего лока даже переносить). Использоваться будут оба диска, что кстати хорошо с точки зрения io.
    Ответ написан
    2 комментария
  • Как замониторить банусер?

    Melkij
    @Melkij
    PostgreSQL DBA
    Нет, сам postgresql о существовании баунсера вообще не знает. pgbouncer является обычным libpq клиентом с точки зрения базы.
    Ответ написан
  • Необходим поменять формат времени в запросе, как?

    Melkij
    @Melkij
    PostgreSQL DBA
    формат времени с mysql на postgresql

    done by sql design.
    Форматы даты, времени, датывремени эквиваленты. И, емнип, вовсе стандартны для SQL в целом.
    Если вы пихаете данные в неподходящий тип данных вместо штатного для обеих субд timestamp - то вас будут ждать сюрпризы рано или поздно. Это как бы само собой разумеется.

    Если ваш clock, как очевидно по комментарию в другом ответе, int4 является количеством секунд с начала этой эпохи, то привести unixtime к циферке-количеству-секунд-этой-эпохи можно через extract:
    hs.clock > extract(epoch from timestamp 'yesterday')

    Привести циферку количества секунд в этой эпохе к timestamp можно функцией to_timestamp.
    Ответ написан
    2 комментария
  • Как мне отсортировать кверисет?

    Melkij
    @Melkij
    PostgreSQL DBA
    Какой запрос идёт в базу в результате?
    Если не указано никакого order by - то порядок записей в результате запроса любой. В смысле действительно любой, СУБД может даже на каждый запрос возвращать данные в разном порядке и это именно то, что сказано в стандарте SQL.
    Ответ написан
    Комментировать
  • Как выгрузить из бэкапа нескольких БД одну необходимую?

    Melkij
    @Melkij
    PostgreSQL DBA
    Как выгрузить из бэкапа нескольких БД одну необходимую?

    бэкап всех БД - all_databases.sql

    Никак.
    Либо идти руками и текстовым редактором доставать именно нужное.

    -U - существующий в postgresql пользователь, от имени которого можно зайти сейчас. А не после разворачивания бекапа. Для бекапа всего кластера очевидно понадобится суперпользователь, postgres или pgsql обычно.
    -d имя базы данных, а не таблицы. База так же должна уже существовать, чтобы можно было подключиться к pg.
    Ответ написан
  • Postgres не обновил sequence при вставке с PK?

    Melkij
    @Melkij
    PostgreSQL DBA
    Потому что не был вызван nextval. За ненадобностью.
    Раз не нужно было генерировать новое значение, то зачем его дёргать зря?
    Ответ написан
    6 комментариев
  • Как осуществить выборку повторяющихся событий из базы?

    Melkij
    @Melkij
    PostgreSQL DBA
    Если в лоб:
    select ... from events where exists (
        select 1 from generate_series(events.start_date, :target_end_date, events.repeat) as d(rep_date) 
        where rep_date between :target_date and :target_end_date
    );

    Как сделать быстро сходу не сообразил.
    Ответ написан
    Комментировать
  • Как правильно подсчитать примерное количество строк через EXPLAIN?

    Melkij
    @Melkij
    PostgreSQL DBA
    Поизучайте как именно работает статистика планировщика. Ну, например, https://habrahabr.ru/company/pgdayrussia/blog/329542/
    Есть default_statistics_target (дефолт 100) и именно столько штук самых популярных конкретных значений отслеживается в most_common_vals и most_common_freqs. Что можно сказать про все остальные значения? (число разных значений есть - n_distinct) Что они как-то могут быть распределены по (100%-sum(most_common_freqs)) оставшимся строкам. В сущности, в статистике нет других значений кроме most_common_vals и потому нельзя сказать, есть ли вообще хоть одно искомое значение. А как они там распределены, если есть? Да кто их знает. Планировщик предполагает, что примерно равномерно.

    Соответственно можно крутить default_statistics_target для конкретного поля или индекса.
    Ответ написан
    1 комментарий
  • Репликация. Правильно ли я понимаю?

    Melkij
    @Melkij
    PostgreSQL DBA
    гарантирует ACID где буква «C» означает Consistency — Согласованность.

    В пределах одного кластера postgresql. Т.е. одного сервера.

    возможна ли ситуация когда ключи «X» и «Y» уже реплицированны на сервер «B», но еще не реплицированны на сервер «C»? При асинхронной репликации?

    By design. Потому это и названо асинхронной репликой. Между коммитом на мастере и приходом каждого отдельного асинхронного слейва в это состояние всегда будет какой-то временной лаг.
    Но timeline один на всех, т.к. его ведёт мастер. Ситуация, что на B записан только X, а на C только Y - исключена.

    Синхронная реплика - мастер не ответит клиенту "записано" пока не получит отклик от синхронных реплик из synchronous_standby_names, что те получили эти wal (дефолт, гарантирует, что данные есть минимум на двух машинах и при внезапном сбое вы их не потеряете), применили эти изменения (synchronous_commit=remote_write соответственно два кластера postgresql синхронны. Из-за CAP теоремы теоретически возможно, что при сбое мастера на слейве эта транзакция будет уже записана, а на мастере значится как прерванная. Не знаю, что именно по этому поводу сделано).
    Внимание, что при потере работоспособности синхронной реплики мастер будет доступен только на чтение. Все пишущие транзакции будут ждать возвращения синхронной реплики.

    Гарантируется ли согласованность в системе из нескольких реплицируемых серверов?

    Смотря чем вам допустимо жертвовать для этого. См. CAP теорему.

    Это, разумеется, справедливо только для встроенной бинарной потоковой репликации WAL. Логическая в 10 будет жить по своим особым правилам, как и сторонние триггерные решения.
    Ответ написан
    Комментировать
  • Как из таблицы получить массив в postgresql?

    Melkij
    @Melkij
    PostgreSQL DBA
    select array_agg(field) from test
    ?
    Ответ написан
    Комментировать