🏠 О стоимости квартиры в Москве…
Собственная квартира на Брянской улице, кстати, обошлась Воложу по цене двух американских персоналок общей стоимостью 3800 долларов. Техника в то время стоила дорого, а квартиры дёшево: рынок недвижимости ещё толком не сформировался. Квартиру можно было и за видеомагнитофон купить.
— «Яндекс.Книга» (Дмитрий
Благословенные времена. Речь идёт о стоимости квартиры в Москве в Перестройку, насколько я понял из контекста книги. Брянская улица находится около метро «Киевская», очень недалеко от центра.
🐘 Подготовленные планы в PostgreSQL
Но вот какая неприятность — при подключении любого балансировщика нагрузки, совершенно неочевидно куда улетает ваш план и таблица в приложении не помогает — она единая, а серверов может быть несколько, у каждого свои планы подготовленные. Если мы начнём подготавливать его заново, а он уже есть, получим ошибку, что план уже существует.
Какой выход? Краткий ответ: пока никакой.
Самый очевидный — игнорировать такие ошибки. К сожалению, он не подойдёт — если ошибка произойдёт в транзакции, «Постгрес» её просто откатит. Второй выход — не использовать подготовленные планы. Я пока нашёл третий — мы используем планы только если уверены, что они пойдут на мастер — это запросы на изменение
С другой стороны у меня появилась идея — добавить в эскуэль конструкцию PREPARE IF NOT EXISTS, ребята из, с которыми я обсуждал эту идею, PostgresPro уже сделали несколько версий патча.
Основа идеи — всегда слать запрос на компиляцию плана, но если он уже был скомпилирован, ничего не делать. Мы его уже погоняли (оттуда и цифры первого абзаца), но на этом пути больше трудностей, чем себе можно представить — в частности, надо патчить ещё и продукты для балансировки и расширять его клиентский протокол.
Очень надеюсь, что патч доведут до ума и мы скоро сможем его использовать.
💰 Шалаш на острове сокровищ— 4
Сегодня мы побили все рекорды — выехали в половину шестого утра, а вернулись домой в седьмом часу. Обошли несколько домов, результат следующий: «конина», 2 копейки 1924 года (в отличном состоянии, но гнутые), 3 копейки 1946, пуговица братьев Бух царского периода, кольцо (вероятнее всего — «конина»), пуля, шток от умывальника, безымянная пуговица (думаю, современная), странный значок, маленькая пуговичка «Законъ» в плохом состоянии, капсуль от патрона, алюминиевый значок (кажется с Лениным) и пуговица с непонятным гербом.
Последнюю пуговицу не удалось опознать, кажется на ней герб
Ещё была советская медаль «За доблестный труд», но её забрал себе владелец одного из домов, где мы искали и девять советских монет позднего периода в плохом состоянии, их я просто выбросил.
🐘 «Рекурсивные» запросы в PostgreSQL
Одна из главных бед «Постгреса» — бедные (по сравнению с «Ораклом») «рекурсивные» запросы. Подробнее об этом
Если вы знаете рецепт лучше, поделитесь, пожалуйста.
Как я уже рассказывал, поскольку продукт у нас мигрирует с «Оракла» на «Постгрес», мы сейчас живём сразу на двух базах и некоторые виды запросов строят унифицированные билдеры.
Есть такой и для «рекурсивных» запросов. Нередко «рекурсивный» запрос приходится строить, выбирая не из таблицы, а из подзапроса. Наш билдер был устроен таким образом, что подобный запрос он строил по следующему образцу:
WITH RECURSIVE prior AS (
WITH virtual AS (
-- тут у нас подзапрос
)
SELECT … FROM virtual WHERE …некий критерий…
UNION ALL
SELECT … FROM virtual INNER JOIN prior …критерий соединения…
)
SELECT … FROM prior…Ну вот
Эффективнее оказалось убрать внутренний WITH и повторить запрос дважды — в выборе первой строки и внутреннем соединении. Но беда в том, что билдер так сделать не может, а чтобы его научить, нужно было написать парсер запросов — так как критерии соединения должен содержать правильные алиасы. Оборачивание же части запроса в подзапрос тоже даром не проходит — стоимость запроса вырастает.
Я перебрал несколько решений, которые пришли мне в голову и остановился на следующем: в данный момент билдер создаёт временную «вьюху» с определённым именем, которое указывается в качестве источника запроса. Выглядит это так:
CREATE OR REPLACE TEMP VIEW некоеимя AS (
-- тут у нас подзапрос
);
WITH RECURSIVE prior AS (
SELECT … FROM некоеимя WHERE …некий критерий…
UNION ALL
SELECT … FROM некоеимя INNER JOIN prior …критерий соединения…
)
SELECT … FROM prior…Выходит достаточно эффективно, но смущают две вещи:
💰 Шалаш на острове сокровищ—3
Сегодня весь день посвятили «охоте» в домах, в предыдущие выезды это не было основной целью. Обошли несколько домов, в том числе в одной из заброшенных деревень, которая оказалась, без преувеличения, разграбленной — полы вскрыты, всё что можно — выкопано.
Мы, естественно, полы не вскрываем, а просто ищем дома, где время или предприимчивые соседи постарались до нас. В этот раз добыча очень разнообразная.
Сверху и снизу — медные цепочки, скорее всего два обрывка одной более длинной.
В первом ряду — пять копеек 1911 года, 10 копеек 1914 (моё первое монетное серебро!), крышка от небольшого графинчика, свинцовая пломба (думаю, советских времён, на одной стороне «Т», на другой —
Во втором ряду — ранние советы (поздние фотографировать не стал). Это одна копейка 1935 года, и две копейки 1945, 1946, 1949 и 1956 годов.
Некоторые монеты пришлось серьёзно почистить. Проще всего было с серебряной — опустил несколько раз в специализированное средство «Аладдин» и монета чистая, а когда я её подбирал, она была такой тёмной, что я перепутал её с советской.
«Советы» я сначала сварил в соде, чтобы убрать зелёные наросты (наверное это медный купорос), потом положил в уксус, чтобы уменьшить красноту после соды и в конце почистил
🏠 Кирпичи из дома Микляева (Михляева)
Сегодня повторно побывал в Доме Микляева, там вовсю идёт реставрация, за которой очень интересно наблюдать. В частности, к кирпичам «МЧ» добавились другие, с более интересными клеймами.
Клеймо Марии Челышевой, владелицы кирпичного сарая при деревне Малые Клыки в конце 19 века мне попадалось на левом углу дома, в этот раз я разглядел его и справа. Этих кирпичей вообще там много, видимо дом неоднократно ремонтировался.
А это уже
Другой новичок носит клеймо завода, принадлежавшего крестьянину Ивану Афанасьевичу Костину. В 1862 году он основал гончарный, изразцовый и кирпичный заводы в Нижнем Новгороде. Впоследствии был основан «Торговый Дом И.А.Костин с племянниками», кирпичи с клеймами которого попадаются в интернете.
💰 Чистка монет: «никель», ранние «советы»
Вообще монеты я до этого не решался чистить — у меня тут нулевой опыт и я очень боюсь их испортить,
Начал с «никеля», их я нашёл в свой последний выезд. Посмотрел несколько роликов, прочитал несколько рецептов, выбрал один — монеты погружаются в уксус (в моём случае это был 5% раствор) с поваренной солью, а потом дочищаются содой.
Превосходный рецепт, всего за несколько часов довёл монеты до состояния выше. Не надо пугаться, это общая длительность процесса — изредка я наведовался в ванную, чтобы посмотреть как идёт, доставал монеты пинцетом, мыл, чистил и кидал назад.
Учитывая их первоначальное состояние, результат великолепный.
🌀 Мельница в селе Симетбаш
Проезжали с приятелем через село Симетбаш, взгляд привычно зацепился за явно дореволюционную постройку. Пошли смотреть, издалека казалось — либо церковь (которой там быть не должно), либо мельница.
Вблизи ощущение старины постройки усилилось — кованые элементы, восьмискатная крыша. Но здание оказалось заперто, пришлось лезть на крышу — я заметил, что у окна выше не хватает стекла.
Фото выше делал на просунутый в окно фотоаппарат. Это действительно оказалась мельница, с электрическим приводом. Причём действующая до сих пор — к ней подведено электричество.
Гугление ничего не дало, поэтому решил написать в блоге — вдруг кто опознает постройку и расскажет её историю.
💰 Шалаш на острове сокровищ—2
Сегодня постарались целенаправленно поискать монеты по домам. Жилой дом не порадовал буквально ничем, а вот бывший сельский магазинчик принёс 51 монету, правда по большей части — поздние «советы», их я даже фотографировать не стал.
Сверху на фотографии 1 пфенниг ГДР 1977 года, далее по номиналам: 3 копейки 1930 и 53 годов, 5 копеек 1928, 31 (2 штуки), 46, 54 и 55 годов, 10 копеек 1939 года, 15 копеек 1952, 53 и 55 годов, 20 копеек 1948, 54 (2 штуки) и 1957 годов.
Самая старая монета за сегодняший выезд — 5 копеек 1928 года.
👁 Глаз следящий
Обновилась до версии 2.9 моя любимая
Протокол довольно простой:
ESC ] 1337 ; File = [необязательные параметры] : изображение в формате base64 ^GРешил немного с ним побаловаться, результат на скриншоте — небольшая программа на «баше» — глаз, который следит за указателем мыши.
Пришлось разобраться с тем как вообще получают координаты мыши в консоли, плюс вспомнить школьную геометрию. Синусы, косинусы, вот это всё, неявно вычисляются через awk и используются для определения где нужно рисовать зрачок.
Чем дальше курсор находится от глаза, тем больше событий мыши получает консоль во время перемещений по окружности вокруг него.
Для запуска требуется iTerm2 2.9 и выше и Imagemagick.
🔑 Мастер ключей
Это Главный ключ страны, мы называем его «Ключ № 1 СССР». Он от входной двери в Мавзолей.
Согласитесь, что мне было бы очень трудно объяснить следователям КГБ, зачем и с какой целью я срисовал этот ключ в масштабе 1:1, если бы меня поймали за этим занятием.
Но к счастью, мне удалось сделать это незаметно, а поскольку срок давности за это преступление давно истёк, я предлагаю читателю полюбоваться на этот ключ. Правда же, он очень красивый?
Цитата из книги «Байки старого телемастера» Геннадия Гендина. Очень и очень рекомендую книгу, совершенно роскошная, читается на одном дыхании. Будет интересна буквально всем своими уникальными деталями советского быта — по роду работы автор был вхож в дома многих советских деятелей и даже в Кремль. Ключ, которые вы видите выше, он срисовал именно там.
⌨ Детская Вычислительная Машина (ДВМ-1М)
Всё идёт к тому, что Музей Вычислительной Техники, открытию которого я всеми силами помогаю, будет весьма любопытным уже на первых этапах. Сейчас ко мне в руки попала «Детская Вычислительная Машина» 1983 года выпуска. Между прочим, это первая машина, на которой я
«Машина» в прекрасной сохранности, которую чуть подпортили
Эта приехала ко мне из Новосибирска, а в моём детстве такая же была у сына соседей снизу — мы с ним дружили и я иногда спускался к нему, играть на ДВМ. Прекрасно помню саму «Машину», эти перемычки и штырьки, но память совсем не сохранила карточки, фишки и кубик — генератор случайных чисел.
В книжке одиннадцать «программ» (есть даже такие, где нужно играть вдвоём!), для некоторых из них и нужно это дополнительное «оборудование».
Программа вводится при помощи перемычек и штырьков, после чего надо сдвинуть все три планки в соответсвии с правилами и получить ответ в двоичном виде, нажав на специальную кнопку. Возможно
На фотографии выше программа «Угадай число». Требовалось всё правильно скоммутировать, загадать число от нуля до семи и ответить на три вопроса, выставляя планки в соответствии с ответами.
Я загадал пять. В ответах на вопросы надо было указать чётное ли число, меньше ли восьми сумма задуманного числа и следующего за ним и равняется ли 4 или 5 остаток от деления на шесть суммы задуманного числа и 10? Для моего числа — «пятёрки», ответ на все вопросы — «нет» («ноль»).
После нажатия на кнопку, машина дала ответ в бинарном виде — надо сложить четвёрку и единицу. Интересно, что я показывал эту «программу» трём различным людям и все загадали именно это число.
Так же в коллекции музея теперь есть и «Детская Логическая Машина» — старшая сестра (по возрасту, а не умениям)
🐘 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, но она, насколько я понял из руководства, лишь сбрасывает различные конфигурационные переметры времени выполнения на значения
💰 Шалаш на острове сокровищ
В общем, теперь я обладатель: одной копейки 1885 года, одной копейки 1897, трёх монет по ¹⁄₄ копейки — одной 1873 года и двух 1878, одной копейки «ранних советов» — 1957, двух свинцовых пломб (одна без надписей, на второй надпись — «Шмидтъ. Лодзь. Шелк. Полуш…») и серебряного колечка
Надпись на пломбе, как удалось выяснить, полностью выглядит так: «Фабр. шерст. полушел. и шелк. изд. // Шмидтъ и Пфитце — Лодзь».
Отдельной строкой. Очень радует сохранность монет, вот что значит не в земле лежали. Следы окисления есть, но большей частью монеты выглядят просто превосходно.
🚨 Особенности перехода с «Оракла» на «Постгрес»
В комментариях пообещал поописывать свой опыт перевода продукта с «Оракла» на «Постгрес», особенно в особенностях, которым очень мало уделено внимания на просторах интернета. Начну с простого, зато сразу целой пачкой. Примеры я, естественно, упростил, чтобы максимально выпукло продемонстрировать различия.
У нас довольно много генерируемых простых запросов, иногда они генерировались не очень аккуратно. «Оракл» такое прощает, а «Постгрес» — нет. Запрос, где одни и те же таблицы соединяются дважды «Постгресу» не по вкусу:
SELECT * FROM test INNER JOIN test1 USING(n) INNER JOIN test USING(n);
ERROR: table name "test" specified more than once«Постгрес» очень трепетно относится к тому, чтобы у подзапроса был алиас, даже если он потом нигде не используется:
SELECT * FROM (SELECT * FROM test);
ERROR: subquery in FROM must have an alias
СТРОКА 1: SELECT * FROM (SELECT * FROM test);
^
ПОДСКАЗКА: For example, FROM (SELECT ...) [AS] foo.В «Постгресе», в запросах на обновление нельзя указать алиас. Тут это логично, так как синтаксис подзапросов в этом случае у этой СУБД совершенно иной — они указываются в специальном месте.
UPDATE test t SET t.n=1;
ERROR: column "t" of relation "test" does not exist
СТРОКА 1: UPDATE test t SET t.n=1;Если «Оракл» спокойно относится к двум и более таблицам с одним алиасом, то «Постгресу» от этого плохеет. Жаль, иногда удобно объединить несколько таблиц алиасом прямо на месте и работать дальше с ним, как с единой таблицой.
SELECT t.n FROM test t, another_test t;
ERROR: table name "t" specified more than onceВ «Оракле» ключевое слово FROM не обязательно в запросах на удаление. У нас было несколько запросов без него.
DELETE test;
ERROR: syntax error at or near "test"
СТРОКА 1: DELETE test;В следующий раз буду описывать более комплексные примеры.
⌨ Ещё партия советской техники в музей
Подоспела партия новых экспонатов в музей вычислительной техники, который я помогаю организовывать. Это БК
Бонус — кот Е́жи
❌ Приметы девяностых
Сейчас многие говорят о кризисе и в этой связи — о возвращении девяностых. У многих упали доходы, как следствие по всей стране выросла преступность (в Казани — на 20% в прошлом году).
Недавно у одного моего знакомого сняли дворники с машины.
Хотя этот случай не показателен, это прямая ассоциация с девяностыми, тогда, я помню, оставляя машину, все снимали дворники так как крали их постоянно.
Я не уверен, что они именно тогда они и появились, однако могли бы — в те времена тащили всё что угодно, оконные стёкла в том числе. А такая пометка, я так это интерпретирую, помогала предотвратить кражу. И теперь, когда я их вижу на стёклах, доживших до нашего времени с тех времён, моя память подкидывает мне чёткую и однозначную ассоциацию.
А что для вас является персональной ассоциацией с тем временем? Я не имею ввиду одежду не по размеру, бандитов и всего того, что обычно люди обычно вспоминают.
✨ Двойные миграции (Оракл+Постгрес)
У нас идёт замена в наших продуктах сильно платного «Оракла» (это база данных) на бесплатный «Постргес». Несмотря на ударные темпы, продолжаться это ещё будет долго. Продуктов много, несмотря на то, что начали мы ещё в прошлом году, весь этот год будем жить сразу на двух базах.
В этой связи, когда есть различия, приходится миграции писать в двух комплектах — под каждый диалект. Я придумал как писать их так, чтобы каждая БД видела куски кода, предназначенные только ей.
Например:
CREATE UNIQUE INDEX dn_part_num_org_n_cat ON document_n(/*/**/
CASE WHEN d_deleted = 0 AND num IS NULL AND n=0 AND category=0 THEN id END,
CASE WHEN d_deleted = 0 AND num IS NULL AND n=0 AND category=0 THEN org_id END);
--*/ id, org_id) WHERE d_deleted=0 AND num IS NULL AND n=0 AND category = 0;Часть с /*/**/ и до —*/ видит только «Оракл» — для него это выглядит так: комментарий открывается, сразу закрывается, идёт код, который он и воспринимает, а последняя строка закоментирована при помощи двух минусов — это стандартный коментарий в эскуэле.
«Постгрес» эту часть не видит — он поддерживает вложенные коментарии, поэтому его интерпретация другая: открываются два комментария, первый закрывается сразу, а второй — на последней строке, остаток которой «Постгрес» воспринимает как часть кода.
⌨ Советские калькуляторы в музей
Скоро передам в готовящийся к открытию музей несколько советских и постсоветских калькуляторов. Слева направо: две «Электроники МК 51» (1992 и 1994 гг.), «Электроника
🔍 Линза на телевизоре
В субботу был в музее Истории Сибирского тракта (село Карадуван) и обратил внимание на одну деталь, которую
Я нередко вижу в музеях телевизоры с линзами, но впервые обратил внимание на то, что эти линзы заполняли водой. Мне
Разглядывая свою фотографию из казанского музея Счастливого детства, я заметил, что линза верхнего телевизора
На всякий случай проверил версию, что сотрудники музея заполнили линзу водой по незнанию (всякое бывает). Хотя это было маловероятно — в карадуванском музее смотрительница даже вынула пробку из входного отверстия и показала как это делалось с полным знанием вопроса.
В общем, нашёл в интернете инструкцию к одной линзе тех времён и она недвусмысленно опровергает это сомнение. Кстати, иногда вместо воды использовали глицерин — у него другие характеристики преломления и линза давала большее увеличение.