Задать вопрос
  • Как правильно составить запрос для взятия первого значения из группы?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Ну а когда станет скучно перебирать всю таблицу - обращайтесь :-)

    Postgresql 9.4 и выше, выбор по известному диапазону дат через index scan по timestamp полю:
    select day, data 
    from generate_series('2017-12-10', '2017-12-12', interval '1 day') as day, 
    lateral (
        select data from tablename 
        where "timestamp" between day and day + interval '1 day' 
        order by "timestamp" desc limit 1
    ) ljd;


    Все дни из таблицы по индексу:
    with recursive t as (
    (select "timestamp"::date as day, data from tablename order by "timestamp" desc limit 1)
    union all
    select bpt.* from t, lateral (
    select "timestamp"::date as day, data from tablename where "timestamp" < t.day order by "timestamp" desc limit 1
    ) as bpt
    )
    select * from t;

    Используя loose index scan
    Ответ написан
    7 комментариев
  • Как искать в моделях yii2 с использованием DATE_FORMAT?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Потому что не надо так искать год. Ваш запрос ведёт к сканированию всей таблицы, либо, в лучшем случае - к необходимости делать отдельный функциональный индекс по этому выражению.
    Сделайте запрос на диапазон
    date_label >= '1994-01-01' and date_label < '1995-01-01'


    Видимо как-то вот так:
    ModelName::find()->where(['between', 'date_label', '1994-01-01', '1995-01-01' ]);
    Ответ написан
    1 комментарий
  • Почему не находит php7.1-mysql_7.1.12?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Открываем ppa.launchpad.net/ondrej/php/ubuntu/pool/main/p/php7.1 и смотрим, что там есть.
    Там есть
    php7.1-mysql_7.1.12-2+ubuntu17.10.1+deb.sury.org+2_amd64.deb

    А вы хотите получить:
    php7.1-mysql_7.1.12-1+ubuntu17.10.1+deb.sury.org+1_amd64.deb

    Следовательно, вы не выполнили обновление списков пакетов в репозиториях и таким образом пытаетесь получить старую версию пакета, уже удалённую.
    Необходимо сделать apt-get update, aptitude update, apt update - смотря чем пользуетесь.
    Ответ написан
    2 комментария
  • Как оптимизировать sql запрос с несколькими Join-ами в ActiveQuery Yii2?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    disabled и date_added - в таблице announcements

    Так нафига вам вообще любой из указанных join'ов равно как и distinct?!
    Вы из них абсолютно никак не читаете и не используете. Так зачем? Просто размножить строки и героически их склеить обратно distinct'ом?

    SELECT `announcements`.* FROM `announcements` 
    WHERE `disabled` = 0 
    ORDER BY `date_added` DESC 
    LIMIT 15
    Ответ написан
  • Как в PostgreSQL выбрать значения значения которые есть в массиве, но нет в БД?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Всё просто: надо развернуть массив в набор строк и проверить на not exists
    select i from unnest(array[1,2,3,4]) as i 
    where not exists (select 1 from tablename where id = i);
    Ответ написан
    9 комментариев
  • Как подсчитать кол-во вставленных записей в БД?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Мне неизвестны штатные средства для этого.

    В качестве обходных фокусов можно поизвращаться вот так:
    with 
    data (new_user_id, new_name) as (values(%(user_id)s, %(name)s)),
    wr as (
        INSERT INTO users(user_id, name)
                    select new_user_id, new_name from data
                    ON CONFLICT (user_id) DO NOTHING returning user_id
    ), upd as (
        update users set name = new_name from data where users.user_id = data.new_user_id and data.new_user_id not in (
        select user_id from wr
        )
    )
    select count(*) from wr;


    Что работает согласно задаче из-за того, что do nothing не осуществляет insert и потому строка не появляется в returning.
    Ответ написан
    Комментировать
  • Стоит ли хранить файлы транзакций отдельно от баз?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Имеются в виду pg_xlog (pg_wal в 10) или pg_clog (pg_xact)? Файлы (метаданных) транзакций - это вторые и пишутся они не очень интенсивно. Первый - write ahead log - журнал записи, где отражается вся пишущая активность базы и обычно синхронной записью.

    Производительность дисков для записи WAL - это ключевой фактор для времени commit. Но WAL пишется последовательно и за счёт этого можно держать вполне хорошую нагрузку размещая их монопольно на отдельных HDD, а не SSD. Сэкономив соответственно немного денег на требуемой под базу ёмкости SSD.
    Ну или если у вас записи достаточно много при нормально настроенных checkpointer и bgwriter, чтобы была необходимость выделить отдельные несколько SSD под WAL. Впрочем, у вас в тегах NTFS упомянут. На таком нормальный production всё равно не делают, значит не ваш случай.

    Массивы - RAID10 или RAID1 смотря сколько дисков есть. Для тестовых машин смотрите сами.
    Ответ написан
  • Как случайно выбирать математическое действие?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Различие только в +0, +$D или -$D?
    $array_col2[$i] = ($array_col1[$i] + $D * mt_rand(-1,1));

    Вот и вся логика.
    Ответ написан
    1 комментарий
  • Как быть с CURLOPT_POSTFIELDS и file_get_contents?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_INFILE, fopen('pathtofile', 'rb'));

    Должно быть то что нужно.
    Ответ написан
    2 комментария
  • Вставка записи в главную таблицу и подчиненные?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Добавить ещё один CTE.
    WITH new_tbl_main( id ) AS (
              INSERT INTO tbl_main ( institution_id ) VALUES ( 38)
                RETURNING id 
    ), chi2 as (
    INSERT INTO tbl_child1 ( tbl_main_id ) 
                SELECT new_tbl_main.id  FROM new_tbl_main
    )
    INSERT INTO tbl_child1 ( tbl_main_id ) 
                SELECT new_tbl_main.id  FROM new_tbl_main
                RETURNING tbl_main_id

    Если нужен returning от всех - то добавить ещё cte и в финале склеить запросы через union all или join или как понравится.
    Ответ написан
    Комментировать
  • Как правильно создать функцию возвращающую булевый результат выполнения селекта?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Вероятно при упрощении примера вы выкинули собственно саму причину синтаксической ошибки.
    Потому что приведённая в вопросе хранимка синтаксически корректна, что, впрочем, не изменяет некорректности семантической.
    ERROR: cannot use RETURN QUERY in a non-SETOF function

    Вы не можете использовать return query для возврата одного значений. return query только для функций возвращающих множество. Булево выражение можно посчитать непосредственно в return, как в большинстве других языков:
    CREATE OR REPLACE FUNCTION checkPermission(text, text) RETURNS BOOLEAN AS
    $$
    BEGIN
      RETURN $1 && $2;
    END;
    $$ LANGUAGE plpgsql


    Ну и мелочь лучше записывать на language sql, что позволяет оптимизаторы делать интересные фокусы в целях повышения производительности запросов.
    CREATE OR REPLACE FUNCTION checkPermission(text, text) RETURNS BOOLEAN AS
    $$
      SELECT $1 && $2;
    $$ LANGUAGE sql


    Разумеется, это будет работать только если у вас определён оператор && для пары операндов типа text.
    Ответ написан
    Комментировать
  • Как правильно найти пересечение двух jsonb массивов в postgres?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Есть у постгреса оператор &&

    "есть оператор" - это сказано немного сильно преждевременно. Например, на моей тестовой 9.6 таких операторов 8 штук.
    Потому что нет отдельно операторов. Операторы определены только неразрывно с типами данных своих операндов (двух или одного для префиксных и постфиксных операторов)

    select oprkind, l.typname, oprname, r.typname from pg_operator join pg_type l on oprleft = l.oid join pg_type r on oprright = r.oid where oprname = '&&';
     oprkind |  typname  | oprname |  typname  
    ---------+-----------+---------+-----------
     b       | box       | &&      | box
     b       | polygon   | &&      | polygon
     b       | tinterval | &&      | tinterval
     b       | circle    | &&      | circle
     b       | inet      | &&      | inet
     b       | tsquery   | &&      | tsquery
     b       | anyarray  | &&      | anyarray
     b       | anyrange  | &&      | anyrange

    И jsonb здесь явно отсутствует.

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

    Плюс посмотреть в релевантный jsonb раздел документации: https://www.postgresql.org/docs/current/static/fun...
    Но с операциями на массивами в json там немного печально и неудобно.
    Ответ написан
    Комментировать
  • Как посмотреть, что занимает место на диске linux?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Вероятно запущенные процессы удерживают открытыми дескрипторы уже удалённых файлов, что не позволяет освободить занятое место ФС.

    Список дескрипторов и процессов можно получить например так:
    sudo lsof -a +L1
    Пример строки от меня:
    COMMAND     PID   USER   FD   TYPE DEVICE   SIZE/OFF NLINK    NODE NAME
    php       17455 melkij    4r   REG  254,1 1048576000     0 2624572 /home/melkij/tmpfile (deleted)

    php процесс с pid 17455 удерживает deleted дескриптор файла размером в 1гб.

    Далее адресно разбираться с процессами.
    Ответ написан
    3 комментария
  • Как использовать huge pages для Postgres запущенного в docker контейнере?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Не извращаться и вытащить production базу из докера на нативное железо. Что базе в этом докере делать, если и диск и сеть надо использовать хоста?

    Насколько я помню, ни cgroups ни namespaces не мешают выделенным huge pages. Попробуйте вкрутить vm.nr_hugepages на хост системе и стартовать базу с huge_pages=on
    Ответ написан
    Комментировать
  • Как правильно реализовать структуру бд для многопользовательской платформы?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    У конструкторов типичный workload - около нуля на большинство площадок и небольшой процент активных. Заворачивать индивидуально каждого в свою БД - сильно утомительно в поддержке. Дожили до 1000 созданных сайтов (что не так уж много если не сказать "вообще крохи") - у вас 1000 баз, что уже весьма дофига. Выкатить в прод новую версию приложения - уже приключение.

    Если вы хотите SaaS - т.е. у конечных пользователей прямого доступа в БД нет никакого - то в поддержке сильно проще будет классическая схема шардирования. К тому же у вас данные разных клиентов заведомо по предметной области никак не пересекаются.
    - в таблицах специфичных для клиентов вводится site_id и входит в уникальные ключи и прочее счастье ограничений целостности (для postgresql можете дополнительно прикрутить row level security и база будет дополнительно приглядывать)
    - отдельно размещается ваш биллинг и управление пользователями, где помимо прочего пишете таблицу соответствия, какой site_id расположен на каком физическом хосте и в какой базе данных (плюс список ro-реплик)
    - закешировать соответствие сайта базе можно в каком-нибудь redis и ходить с одного единого пула серверов приложений что сильно проще по масштабированию приложения (если сервер приложения рассматривать как stateless, что опять же сильно проще в поддержке).

    В итоге схема позволяет работает с осмысленным числом крупных баз (начиная с одной и вводя новые по необходимости), неактивные сайты мигрировать в архивные базы, горячие от дорогих клиентов - выделять хоть даже в отдельную инфраструктуру. Кстати, фокус с отделением vip-клиента в отдельную инфраструктуру позволяет дать этому клиенту и прямой доступ в базу при необходимости и возможность пилить кастомный функционал именно для него.
    Ответ написан
  • Как в Mysql суммировать средние значения?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Просто добавьте ещё один select
    select sum(amount) from (
        select avg(/**/) as amount
        /* ... */
    ) total
    Ответ написан
  • Можно ли поставить разные таймзоны в типе datetime with timezone postgresql?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    timestamp with time zone приводит и хранит данные только в UTC и переводит их в местное время при чтении согласно сессионной настройке timezone.

    https://www.postgresql.org/docs/9.6/static/datatyp...
    For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's TimeZone parameter, and is converted to UTC using the offset for the timezone zone.


    timestamp without time zone вовсе игнорирует указание в литерале временной зоны.

    а других timestamp и нет. Поэтому нет, хранить таймзону (при необходимости в этом) необходимо отдельно. Зато за счёт этого timestamp занимает всего константные 8 байт.
    Ответ написан
    Комментировать
  • Вопрос по статье на Хабре про триггеры - могут ли гарантировать триггеры целостность данных?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    но как переменная current_amount попадет внутрь триггера?

    Автор статьи не стал вдаваться в детали какой-либо СУБД, поэтому уточняйте в документации к своей СУБД.
    Для for each row триггеров обычно можно читать из NEW.amount в after insert триггерах.
    Для for each statement - смотрите документацию к своей СУБД.

    либо ограничить инсерты\апдейты (разрешив их только вызовами изнутри sql-сервера), но мне кажется, что sql-сервер не позволяет добавлять такие ограничения на таблицы

    Смотрите опять же документацию к своей СУБД.
    Для postgresql такую модель прав сделать можно. Для этого необходим отдельный пользователь для деплоя приложения (вообще полезная штука всегда) и security definer триггер.

    могут ли гарантировать триггеры целостность данных?

    Могут, но бывают сюрпризы. Например, mysql вам не запретит из триггера на ACID табличке что-то делать с myisam. Последующий rollback транзакции по любой причине = у вас потеря целостности. Впрочем, если вы знаете о целостности данных - то вы и не станете использовать всякое myisam.
    Ответ написан
    Комментировать
  • Почему не работает UNION ALL запрос?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    Потому что имеет на то право.
    https://dev.mysql.com/doc/refman/5.7/en/union.html
    Use of ORDER BY for individual SELECT statements implies nothing about the order in which the rows appear in the final result


    select /*payload*/ from user
    where rank_golos >0
    order by rank_golos >=22.1 desc, 
      if (rank_golos >=22.1, rank_yearnub, rank_golos) desc,
      if (rank_golos >=22.1, rank_golos, rank_yearnub) desc

    Если типы rank_golos и rank_yearnub могут быть приведены к общему виду.
    Ответ написан
    2 комментария
  • Выбрать первую и последнюю запись группы?

    Melkij
    @Melkij
    DBA для вашего PostgreSQL?
    В смысле вот так?
    select ticket_number , min(some_id), max(some_id) from tablename group by ticket_number
    Ответ написан