Ответы пользователя по тегу PostgreSQL
  • Журналирование в mongodb и postgresql - правильно ли я его понимаю?

    Melkij
    @Melkij
    PostgreSQL DBA
    Точно про актуальную монгу сказать что-то затрудняюсь.
    Про версию постарше цитата про вторую версию монги
    MongoDB v2.0 will consider a write to be complete, done, finito as soon as it has been buffered in the outgoing socket buffer of the client host.

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

    и тут я вспомнил что у postgresql есть параметр wal_writer_delay = 200ms, что-же получается и у postgresql может быть такая ботва что клиент думает что строка сохранена а все накрылось до сброса журнала на диск???

    Если вы намеренно выкрутили гайку synchronous_commit.

    fsync - это очень дорого. Даже на SSD.
    Поскольку это дорого, делаются какие-нибудь фокусы. Магнитные диски ненавидят случайную запись и куда лучше относятся к последовательной. Поэтому и тут тоже придумывают какие-то фокусы.
    В итоге postgresql (если вы сами не отстрелили себе ноги) пишет wal в память, отдельный процесс каждые wal_writer_delay просыпается, сбрасывает на диск накопленные wal и отмечает, в какой позиции wal гарантированно доехал до диска fsync. Поскольку synchronous_commit включен, то перед ответом клиенту "записано" воркер ждёт, пока его данные не будут записаны на диск. После этого отвечает приложению "записано".
    https://www.postgresql.org/docs/current/static/run...
    synchronous_commit (enum) Specifies whether transaction commit will wait for WAL records to be written to disk before the command returns a "success" indication to the client
    Ответ написан
    2 комментария
  • Какой должен быть размер базы при дампе?

    Melkij
    @Melkij
    PostgreSQL DBA
    Во-первых, индексы. В sql-дампе любой индекс - это несколько десятков байт запроса на создание индекса. В базе - это развесистая структура, которая может занимать порядочно места. Один индекс обычно небольшой - но у вас же он не один?
    Во-вторых, как уже упомянули - бинарные файлы могут быть раздуты из-за delete и update запросов, если плохо настроен автовакуум. Касается как самих таблиц, так и индексов.
    Третье: например табличка связей из тройки интов. В pg_dump данные пишутся через copy - один заголовок, следом все строки, значения разделены табуляцией. Итого 3 байта на строку данных оверхеда + строковое представление значения. В реальной таблице - у каждой строки есть заголовок из 23 байт. Плюс выравнивание данных. Итого минимум будет 36 байт на каждую строку. (описание структуры таблицы опять же отдельно хранится) Т.е. текстовый вид внезапно компактнее почти на всём диапазоне значений инта для этой таблички.

    Так что да, текстовый дамп может весить сильно меньше бинарного за счёт исключения всех служебных структур.
    Ответ написан
    1 комментарий
  • Почему DISTINCT ON так медленно выполняется?

    Melkij
    @Melkij
    PostgreSQL DBA
    Ускорить можно вот такой милой рекурсивной cte'шкой: https://wiki.postgresql.org/wiki/Loose_indexscan
    Нативно pg пока не умеет loose indexscan. Поэтому distinct читает все элементы дерева вместо поиска следующего большего элемента.
    Ответ написан
  • Как убедить PostgreSQL использовать индекс?

    Melkij
    @Melkij
    PostgreSQL DBA
    у меня есть таблица, в которой уже есть список уникальных меток

    try this:
    select label, latest_stamp from labelstable lateral (
        select timestamp as latest_stamp from tablename where tablename.label = labeltable.label
        order by timestamp desc limit 1
    ) l

    Postgresql 9.3 или выше.
    Loose index scan по самой таблице тоже можно сделать, он просто будет более многословным.
    Ответ написан
    1 комментарий
  • Как сформировать выборку уникальных объектов в массив?

    Melkij
    @Melkij
    PostgreSQL DBA
    select json_agg(json_build_object('id_user', id_user, 'data', d)) from (
        select id_user, json_agg(json_build_object('data', val, 'type', type)) as d from (
            select id_user, type, val from tt group by id_user, type, val
        ) t group by id_user
    ) s;
    Ответ написан
    4 комментария
  • Как сформировать выборку в массив из повторяющихся записей?

    Melkij
    @Melkij
    PostgreSQL DBA
    select id_user, array_agg(data) from tablename group by id_user

    Можно и сразу json собрать. С оглядкой на версию базы только.
    select json_agg((
    select json_build_object('id_user', id_user, 'data', json_agg(data)) from tablename group by id_user
    ));
    Ответ написан
    7 комментариев
  • Как ускорить RETURN QUERY EXECUTE?

    Melkij
    @Melkij
    PostgreSQL DBA
    Зачем здесь query execute? Запрос же статичен.
    RETURN QUERY SELECT "id", "name" FROM "mytable" WHERE date BETWEEN t1 AND t2;

    Впрочем, планировать 1,7с тут в общем-то нечего, так что это спички.

    Вообще, вызов хранимки материализуется. Рабочая гипотеза - на материализации время и тратите. Что дальше происходит с данными? В explain что-нибудь полезное видно? (давненько я хранимки не разбирал, не помню, что туда попадает)
    Ответ написан
  • Как исправить character with byte sequence 0xd0 0x92?

    Melkij
    @Melkij
    PostgreSQL DBA
    Поскольку postgresql сказал, какие это кодировки - значит он о них знает. Самое очевидное - у вас разные кодировки соединения и самой базы данных.

    Сама ошибка говорит о том, что в кодировке latin1 нет эквивалента для символа. Чтобы не иметь себе мозг многими проблемами - пересоздайте (да, именно пересоздайте, кодировка БД может выбираться только при создании БД) базу данных с кодировкой UTF8.
    Ответ написан
    Комментировать
  • Как правильно написать запрос на выборку из базы PostgeSQL?

    Melkij
    @Melkij
    PostgreSQL DBA
    Если только поправить запрос, который у вас на той же схеме работает в mysql:
    SELECT p.phone,
    count(1) filter(where i.status=7 ) as saled,
    count(1) filter(where i.status=3 ) as no_saled
    FROM items as i
    INNER JOIN phones as p
    ON i.user_id=p.users
    WHERE p.phone IN("7924445544", "8985545444")
    GROUP BY p.phone;


    Если же схема другая - то синтаксисом int[] обозначается массив из integer, такой штатных тип данных. В mysql такого нет. У вас именно массив чисел?
    Ответ написан
    1 комментарий
  • Есть ли в оконных функциях PostgreSQL аналог Ораклового count?

    Melkij
    @Melkij
    PostgreSQL DBA
    postgresql не делает явных различий между аггрегирующими и оконными функциями. Как оконную можно использовать любую аггрегирующую функцию (кроме указанных с списке (или своих реализованных как) Ordered-Set и Hypothetical-Set).

    any built-in or user-defined normal aggregate function (but not ordered-set or hypothetical-set aggregates) can be used as a window function

    https://www.postgresql.org/docs/current/static/fun...
    Ответ написан
    Комментировать
  • Где ошибка в запросе?

    Melkij
    @Melkij
    PostgreSQL DBA
    Если вы не указываете, как сравнивать строки таблиц между собой - вы получите декартово произведение. Каждая строка сджойнится с каждой.

    Если вы хотите вывести все данные из обеих таблиц с отметками, что есть только в первой, что только во второй, а что в обеих - вам нужен full join с объединением по этому полю.
    select table1.items, table2.items from table1 full join table2 using(items)
    Ответ написан
    Комментировать
  • Функция копирования строки БД PostgreSQL, как правильно написать?

    Melkij
    @Melkij
    PostgreSQL DBA
    insert into tablename (field1, field2, field3) 
    select field1, field2, 'new values instead field3'
    from tablename
    /*where*/
    Ответ написан
  • Стоит ли делать составные внешние ключи в БД?

    Melkij
    @Melkij
    PostgreSQL DBA
    1. внешние ключи должны быть там и те, чтобы гарантировать ссылочную целостность. Должна быть ссылка сочетанием именно двух параметров - значит должна быть ссылка сочетанием пары параметров. Лучше или хуже сюда не применимо. Два разных fk и один составной имеют различное поведение.
    2. для какой именно СУБД? Postgresql следуя стандарту SQL обязывает ссылаться только на уникальное поле. Mysql отступает и в этом вопросе от стандарта и позволяет проверять неуникальное индексированное поле.
    3. см. coding standart конкретного проекта. Обычно никто не обижается против именования: имя таблицы _ имена полей _fk
    4. можно упереться в предел размера индексируемого поля. У postgresql это 1/3 размера странички памяти = 2730 байт по дефолту, у mysql - зависит от кучи факторов.
    Ответ написан
    Комментировать
  • Как реализовать работу баз данных с разными дисками?

    Melkij
    @Melkij
    PostgreSQL DBA
    Ответ написан
    Комментировать
  • Как преобразовать 1e-06 в 0,000001 в модели Yii?

    Melkij
    @Melkij
    PostgreSQL DBA
    Числа тождественно равны. Ну, насколько это возможно для by design приблизительного double.

    Если надо пользователю показывать в формате десятичной дроби - то внимание на слово "показывать". Значит это вопрос к вьюхе, а не модели. Штатный number_format, например, можно использовать.
    Ответ написан
    1 комментарий
  • Как увеличить скорость скрипта работающего с БД?

    Melkij
    @Melkij
    PostgreSQL DBA
    Возьмите профилировщик и посмотрите, на чём именно теряете время.

    О каком классе СУБД вообще речь?
    Например, если речь о транзакционной РСУБД, строки объёмные, то можно сделать так:
    create temporary table updatetable(guid uuid not null)
    пачками этак по 1000 guid вычитываете guid'ы из источника и записываете в эту временную табличку.
    select guid from updatetable where not exists (select 1 from normaltable where normaltable.guid = updatetable.guid)
    Так получили список guid, которых в целевой БД нет. Сходили в источник за полной версией всех данных этих guid, пачками записали в целевую БД.
    Ответ написан
  • Как подставить значения одной колонки в другие, отсортировав по содержимому этих колонок?

    Melkij
    @Melkij
    PostgreSQL DBA
    У вас табличка ожидаемого результата не соответствует исходным данным.

    Ну, например, так:
    with origtable (name, math, physic, chemie) as (values ('Вася', 80, 52, 69), ('Коля', 50, 90, 95), ('Петя', 62,98, 42)) 
    , orders as (
    select name, 
    row_number() over (order by math desc) as mathid,
    row_number() over (order by physic desc) as phid,
    row_number() over (order by chemie desc) as chid
     from origtable
    )
    select m.name as "математика", p.name as "физика", c.name as "химия" from orders as m                              
    join orders as p on m.mathid=p.phid
    join orders as c on m.mathid=c.chid
    order by m.mathid;


    математика | физика | химия 
    ------------+--------+-------
     Вася       | Петя   | Коля
     Петя       | Коля   | Вася
     Коля       | Вася   | Петя
    Ответ написан
    1 комментарий
  • Какую функцию агрегации использовать в запросе с GROUP BY?

    Melkij
    @Melkij
    PostgreSQL DBA
    Ожидал получить в выборке не более одной строки с каждым ref_id

    GROUP BY ref_id, id

    С чего бы это вы ожидали увидеть только один ref_id, если явно сказали затем группировать по id?
    С учётом названия и того, что postgresql в принципе согласился запрос выполнить - id является первичным ключом. А группировка по первичному ключу ожидаемо результат не изменит.

    select  distinct on (ref_id)  ref_id,  id,  created_at from tablename  order by ref_id, created_at desc;
    Ответ написан
    3 комментария
  • PostgreSQL - как архивировать старые записи в большой таблице?

    Melkij
    @Melkij
    PostgreSQL DBA
    Как разделить таблицу, горячие данные оставить на SSD, холодные - на HDD. Для этого во-первых партицирование для разделения таблицы на две. https://habrahabr.ru/post/273933/ (как обычно, внимание на комменты и pg_partman)
    Затем, до миграции данных (или сразу при создании партиций), перенос архивных в другой tablespace www.postgresql.org/docs/current/static/sql-createt... stackoverflow.com/a/11228536 на HDD.
    Затем миграция данных на партиции.
    Вообще-то, это уже может быть вполне достаточно. 1-2млн строк * 365 дней это не запредельно много. Хотя не указан характер данных.

    Прозрачный для приложения перенос таблиц на другую железку - FDW, foreign data wrapper. Чем актуальнее postgresql - тем лучше. Пилится штука весьма активно по части оптимального распределения запроса. Дружит ли уже с партицированием - честно, не в курсе.

    Прозрачно отправить запрос на две базы и склеить - элементарно view с union all из локальной таблицы и FDW. Только это неинтересный вариант, зачем для запроса на горячие данные дёргать холодную часть базы?

    Вдобавок, можете посмотреть в сторону postgresql-xl, greenplum. Первый года полтора назад был не вполне production-ready, сейчас не знаю, второй используется даже в банковской сфере, но как мне помнится катастрофически не годится для OLTP, только OLAP нагрузка.
    Ответ написан
    1 комментарий