🐘 PostgreSQL, PHP и подготовленные запросы
Одно из отличий «Постгреса» от «Оракла» — подготовленные планы запросов лежат не в разделяемом ресурсе, а в неком хранилище в рамках одного соединения. Программист, в рамках каждого соединения, должен подготовить их оператором PREPARE, в который передаётся выбранный идентификатор запроса и сам запрос, а потом выполнить его при помощи оператора EXECUTE, используя в качестве параметра переданный при подготовке идентификатор и значения параметров.
Польза подготовленных запросов в том, что можно единожды (за время жизни соединения, напоминаю) подготовить запрос, то есть попросить «Постгрес» выполнить его компиляцию в стандартное представление и оптимизацию, а после многократно его использовать, что очевидным образом поднимает производительность приложения.
Схема работы тут очень простая: вычисляем от запроса хеш, ищем его в специальном массиве, если не находим, подготавливаем запрос, используя хеш в качестве идентификатора, после чего хеш добавляем в специальный массив. После чего выполняем подготовленный запрос.
Если план запроса больше не нужен, его можно удалить по идентификатору оператором DEALLOCATE, если же в качестве параметра передать ключевое слово ALL, то будут уничтожены все подготовленные в этом соединении планы. С закрытием соединения, планы так же исчезают.
Теме работы «Постргеса» с ПХП удивительно мало посвящено в руководстве к языку, так что пришлось произвести ряд самостоятельных исследований. Основной вопрос, на который я хотел для себя ответить — есть ли
Оказалось, что это вполне возможно. В ПХП есть «постоянные соединения» — обрабатывающий процесс интерпретатора держит открытым соединение с базой, передавая его новому скрипту, это уменьшает затраты, так как стадия установки соединения и авторизации выполняется только в первый раз.
С открытым соединением в скрипт попадают и подготовленные запросы из предыдущего сеанса, остаётся только
Код всего описанного выглядит вот так, я его упростил и переписал процедурно:
// открываем постоянное соединение с базой
$con = pg_pconnect($connection_string);
// загружаем подготовленные запросы
$res = pg_query("SELECT name FROM pg_prepared_statements");
$prepared = array_fill_keys(pg_fetch_all_columns($res), true);
pg_free_result($res);
// хеш от запроса, tiger — быстрый алгоритм, я люблю его использовать
$hash = base64_encode(hash('tiger160,3', $sql, true));
// смотрим — был ли уже подготовлен такой запрос
if (!isset($prepared[$hash])) {
$prepared[$hash] = true;
pg_prepare($con, $hash, $sql);
}
// выполняем запрос
$res = pg_execute($con, $hash, $params);Общая идея, думаю, понятна из кода. Пока для меня остаётся открытым вопрос «просачиваются» ли в переданное соединение незакрытые транзакции или временные таблицы (предыдущий его владелец, например, мог умереть
Надо заметить, что модуль «Постгреса» в ПХП в каждое соединение, перед его передачей в приложение, посылает команду RESET ALL, но она, насколько я понял из руководства, лишь сбрасывает различные конфигурационные переметры времени выполнения на значения
⌨ Детская Вычислительная Машина (ДВМ-1М)
Всё идёт к тому, что Музей Вычислительной Техники, открытию которого я всеми силами помогаю, будет весьма любопытным уже на первых этапах. Сейчас ко мне в руки попала «Детская Вычислительная Машина» 1983 года выпуска. Между прочим, это первая машина, на которой я
«Машина» в прекрасной сохранности, которую чуть подпортили
Эта приехала ко мне из Новосибирска, а в моём детстве такая же была у сына соседей снизу — мы с ним дружили и я иногда спускался к нему, играть на ДВМ. Прекрасно помню саму «Машину», эти перемычки и штырьки, но память совсем не сохранила карточки, фишки и кубик — генератор случайных чисел.
В книжке одиннадцать «программ» (есть даже такие, где нужно играть вдвоём!), для некоторых из них и нужно это дополнительное «оборудование».
Программа вводится при помощи перемычек и штырьков, после чего надо сдвинуть все три планки в соответсвии с правилами и получить ответ в двоичном виде, нажав на специальную кнопку. Возможно
На фотографии выше программа «Угадай число». Требовалось всё правильно скоммутировать, загадать число от нуля до семи и ответить на три вопроса, выставляя планки в соответствии с ответами.
Я загадал пять. В ответах на вопросы надо было указать чётное ли число, меньше ли восьми сумма задуманного числа и следующего за ним и равняется ли 4 или 5 остаток от деления на шесть суммы задуманного числа и 10? Для моего числа — «пятёрки», ответ на все вопросы — «нет» («ноль»).
После нажатия на кнопку, машина дала ответ в бинарном виде — надо сложить четвёрку и единицу. Интересно, что я показывал эту «программу» трём различным людям и все загадали именно это число.
Так же в коллекции музея теперь есть и «Детская Логическая Машина» — старшая сестра (по возрасту, а не умениям)