Оконные функции (window functions) — это фича, позволяющая производить манипуляции между строками, возвращаемыми одним SQL-запросом. Похоже на GROUP BY, но, в отличие от него, строки не объединяются в одну. Есть задачи, в которых оконные функции исключительно удобны. Например, когда нужно показать некие значения (выручку, посещаемость) за месяц, и рядом с ними — насколько это больше или меньше по сравнению с прошлым месяцем.

Благодаря статье Внутренности PostgreSQL: страницы и кортежи мы узнали, что каждый кортеж в PostgreSQL хранит t_xmin и t_xmax — XIDы транзакций создавшей и удалившей кортеж соответственно. Зная XID текущей транзакции, ее уровень изоляции, а также состояние транзакций t_xmin и t_xmax, СУБД способна определить, виден ли кортеж в текущей транзакции или нет. Узнать состояние транзакции по ее XID можно при помощи ProcArray и CLOG.

Ранее мы разобрались, как PostgreSQL хранит страницы на диске, и как можно посмотреть их содержимое при помощи pageinspect. Но возникает вот какой вопрос. Если размер страницы составляет несколько килобайт, и кортежи не могут занимать несколько страниц, то как СУБД хранит атрибуты с типом TEXT? Ведь строки явно могут быть длиннее пары тысяч символов. Это возможно благодаря штуке под названием The Oversized-Attribute Storage Technique, или сокращенно TOAST.

Одна из возможностей PostgreSQL, которой часто пренебрегают — это NOTIFY и LISTEN. Данный механизм позволяет использовать РСУБД в роли брокера сообщений. NOTIFY/LISTEN обладает рядом полезных свойств, которых нет у прочих решений, таких, как RabbitMQ или Kafka.

Недавно мы разобрались, как PostgreSQL хранит данные на диске. Но как убедиться, что СУБД именно так и работает? Вдруг мы что-то упустили или недопоняли? Можно прочитать данные с диска с помощью утилиты hexdump и посмотреть, что там реально записано. Но это трудоемко, ведь все битики придется декодировать вручную. К счастью, с PostgreSQL идет расширение pageinspect, которое может декодировать битики за нас.

Недавно мы научились напрямую работать с таблицами PostgreSQL из расширений на C. Предлагаю капнуть чуть глубже и разобраться, как PostgreSQL физически хранит данные на диске. Стоит сказать, что представленный материал не претендует на новизну. Вопрос этот хорошо описан в более чем в одном источнике, не исключая официальной документации на PostgreSQL. Однако мне хотелось бы иметь собственную шпаргалку, акцентирующую внимание на наиболее интересных мне лично моментах.

Наиболее простой способ работы с таблицами из расширений PostgreSQL заключается в использовании Server Programming Interface (SPI). С этим интерфейсом мы познакомились в рамках статьи Учимся писать расширения на языке C для PostgreSQL. Однако SPI имеет накладные расходы на парсинг и планирование запросов. Поэтому в простых сценариях выгоднее работать с таблицами напрямую. Звучит страшновато, но на самом деле это не так сложно.

Как мы недавно выяснили, в PostgreSQL есть исключения. Но использовать исключения в языке С, где нет ни автоматического управления памятью, ни умных указателей, не кажется хорошей идеей. Так вот, оказывается, что вместо умных указателей PostgreSQL предлагает совершенно другой механизм — контексты памяти (memory contexts). Давайте же разберемся, что это такое, и чем помогает в работе с исключениями.

Хотелось бы продолжить рассказ о расширениях PostgreSQL и поговорить о логировании и исключениях. Рассматривать их нужно вместе, поскольку в PostgreSQL это связанные механизмы. Хотя ранее мы уже и использовали макрос elog(), тема была затронута лишь поверхностно.

В рамках статьи Учимся писать расширения на языке C для PostgreSQL мы познакомились со структурой расширений для постгреса, узнали, как писать для них тесты, и даже затронули вопрос обновления расширений и использования интерфейса SPI. Но заметка вышла из серии «с места в карьер», без глубокого погружения в детали. А между тем, погружаться есть во что. Хотелось бы заполнить кое-какие пробелы, и начать, пожалуй, следует с Datum и вызова сторонних функций.