На этой неделе возникло острое желание сократить размер PDF-файла, который я генерирую. Нужный мне документ - это этикетка, лейбл, который наносят на посылки размером 6 на 4 дюйма. Это стандартный размер для печати на специализированных термопринтерах для последующего нанесения на посылки. Так вот лейбл, который я генерирую занимает 180Кб и мне стало интересно как можно его уменьшить.
Для начала стоит разобраться, а действительно ли PDF - это подходящий формат? Какие у нас есть варианты? Можно, например, раздавать изображение, но у изображения нет метаданных о размере документа, т.е. размере листа, на котором нужно будет это изображение распечатать. Еще один вариант - это ZPL. Это декларативный язык программирования, с помощью которого можно описать документ, его размер, содержимое. Однако, ZPL без специальных ритуалов нельзя посмотреть на десктопе. Еще один вариант - это LaTeX. Это текстовый язык разметки, созданный около 40 лет назад и до сих пор активно используемый для написания научных публикаций и т.д. Документ в LaTeX легко конвертируется в PDF. Имея некоторый опыт, считаю, что PDF подходит идеально, т.к. он содержит информацию о размере листа, поддерживает встраивание шрифтов и его понимают большинство платформ.
Изучив подробно свой PDF файл я обнаружил, что из 180Кб примерно 140Кб - это встроенные шрифты. Оказалось, что
я встраиваю шрифт целиком, тогда как экономнее встраивать только подмножество глифов,
которые используются в документе. Оказалось, что gofpdf
, если работает не с UTF текстом, то
не сокращает встраиваемый шрифт до набора глифов, которые есть в документа, а встраивает шрифт целиком.
Я перешел на UTF текст и автоматически получил документ размером в 30Кб вместо 180Кб. Шестикратное уменьшение
документа удешевляет их хранение.
Посмотреть глифы, встроенные шрифты в PDF можно утилитой FontForge
. Позволяет как раз посмотреть
глифы шрифта, подправить их при необходимости и т.д. Свободное ПО под лицензией GNU GPL.
Стоит понимать, что PostgreSQL никогда не станет более эффективным key-value хранилищем, чем
специализированный продукт. Если у вас уже есть etcd
или Valkey
(форк Redis),
то переиспользуйте его, но если вы думаете расширять ли стек и у вас уже есть реляционная СУБД,
то предлагаю сегодня обсудить какие ограничения связаны с её использованием в этом контексте. Мы сегодня
будем говорить о простейшем использовании PostgreSQL как хранилища значений key-value.
Если размер ваших данных целиком помещается, в shared_buffers
(напомню, этот конфигурационный
параметр задает размер кеша в оперативной памяти, в котором хранятся страницы памяти диска - нужен для снижения
частоты обращение к жесткому диску, обычно равен 30-40% объема доступного RAM), то производительность будет
умеренно высокой.
Для повышения производительности key-value на базе PostgreSQL стоит также учесть работу HOT (Heap Only Tuple)
и помочь по возможности PostgreSQL. Что такое HOT? Это механизм оптимизации, снижающий
разбухание индексов. B-Tree индекс - это сбалансированное дерево (каждый лист дерева на одинаковой глубине) и
указывает на страницу памяти (обычно 8Кб) и тупл внутри этой страницы. Без работающего HOT когда мы делаем
обновление записи, то на самом деле удаляется старая и создается новая запись и в индекс добавляется новая
запись с тем же PK. Т.е. ситуация когда у нас в индексе есть две записи с первичным ключем - это нормальная
ситуация. VACUUM потом проходится и удаляет старые данные из страниц памяти (Heap) и из индекса.
Если новая запись может уместится на той же 8Кб странице памяти, то срабатывает HOT оптимизация:
индекс останется неизменен, а старый тупл будет помечен как устаревший и у него будет ссылка (редирект) на новый
тупл. Чтобы HOT использовался чаще данные должны быть компактными! Так новая запись будет
чаще умещаться в той же странице памяти. Другой немаловажный параметр - это свободное место на странице памяти,
которое управляется конфгурационным параметром fillfactor
. fillfactor задает количество
занимаемого места при вставках туплов.
Естественно, если возможно, стоит отключить WAL (Write-Ahead Loggin). Вы жертвуете надежностью и возможностью создавать реплики, но выигрываете в производительности. В среднем без WAL производительность выше в 3 раза.
Выводы надо делать каждому самостоятельно в своей конкретной ситуации и под свою нагрузку.