Information
- Rating
- Does not participate
- Location
- Краснодар, Краснодарский край, Россия
- Works in
- Date of birth
- Registered
- Activity
Specialization
Database Developer, Database Architect
Lead
From 500,000 ₽
SQL
PostgreSQL
DWH
Greenplum
ClickHouse
Apache Airflow
ETL
Neo4J
Database
Python
Так мы узнали, что либо в Сбере нет отдела комплаенса, либо его не зовут на акселераторы)
Что-то вспомнились времена в консалтинговой фирме из недружественной страны - там бы такое сразу завернули, ибо харассмент и конфликты интересов из всех щелей
А по-человечески - идея классная, конечно)
К сожалению, это расширение недоступно в Managed PostgreSQL у большинства облачных провайдеров (AWS RDS, например)
Ну и этот табличный API выглядит немного костыльно (на мой вкус)
Одним словом, пилю под свой кейс (PG в AWS RDS + оркестрация через Airflow) собственный велосипед для автоматического партиционирования / пересборки партиций - выложу на Github в ближайшие месяцы
Но покопавшись в этой теме могу сказать, что автоматическое партиционирование в PG - дело весьма нетривиальное, неспроста его нет из коробки. Особенно весёлый кейс - когда в ключе range-партиционирования больше одного поля / выражения (и они ещё могут быть почти любого типа данных). Честно, не заглядывал ещё в исходники partman/pathman по этой теме - интересно, как они решили эту проблему
Тогда при каждом "неоптимальном" add column (например, добавление int-колонки в таблицу с text-колонками), PG пришлось бы автоматически перезаписывать всю таблицу - плохая идея для дефолтного поведения
Ну и в целом, PG среди СУБД - как Linux среди ОС: всегда делает ровно то, что запросил юзер (даже если это выстрел себе в ногу из дробовика)
Хз, но в том же абзаце в доке есть такая фраза про него
Будет хуже
boolean всегда занимает ровно 1 байт, а char(1) займёт 2 байта
https://www.postgresql.org/docs/current/datatype-character.html
Но есть ещё скрытый системный тип "char", который займёт ровно 1 байт (по той же ссылке ниже)
Если писать COPY TO напрямую в файл, то он будет перезаписываться
Чтобы сделать append, можно:
направить COPY TO в STDOUT и перенаправлять STDOUT в целевой файл
направить COPY TO в PROGRAM
Логирование можно делать через автономные транзакции с помощью встроенного расширения dblink (есть из коробки) - можно писать логи в ту же БД, можно писать в другие БД на том же или другом кластере PostgreSQL
Ну или любым из FDW для сброса логов в другие типы хранилищ
У postgres_fdw есть куча настроек для оптимизации DML-операций, которых нет в dblink. Зато через dblink можно делать то же самое + дёргать функции и процедуры, а в postgres_fdw это умышленно не добавляют. Ну и dblink лучше подходит для эмуляции автономных транзакций внутри одной БД
Хайлоад сделать на них не получится, но для вспомогательных операций типа логирования транзакций вполне пойдёт
Я абсолютно не против того, чтобы не пихать бизнес-логику в хранимки
Но те, кто об этом пишет статьи, обычно предлагают такие альтернативы:
аналогичный код на Питоне / JS / PHP..., ещё и обезображенный использованием ORM
dbt и его аналоги, которые в точности повторяют функционал хранимок, но через богомерзкую Jinja
Ещё ни разу не видел кейса, чтобы написали: "мы выпилили хранимки, вместо них написали высокопроизводительный код на С / Java / Rust..., который работает с данными по бинарному протоколу"
А замена хранимок на dbt / функции во внешних скриптах - это тот же половой орган, только в другой руке
--
По поводу именно этой статьи: баянистый сборник мифов о хранимках от человека, который вряд ли когда-то хотя бы пробовал писать на них что-то сложное. Иначе никак не объяснить множественные посылы о проблемах с тестированием - это ж самое простое как раз
Ух ты, кто-то ещё использует MySQL в 2024 году
Ладно б ещё хотя б с MariaDB сравнивали, она и то живее и активнее поддерживает фичи из новых редакций стандарта SQL (system-versioned, bitemporal tables и т. д.)
Сейчас MySQL по функционалу уже скорее с SQLite соперничает, чем с PG
Я плохо знаком с мёртвыми языками типа Пыхи и ещё хуже с его ОРМ, открыл почитать документацию по Yii2
Ну и сразу нарвался на типичную ОРМ-логику - joinWith по умолчанию генерирует два запроса на получение датасетов: левый джойн первой таблицы со второй и выборку из второй таблицы с коррелированным подзапросом (where in (...))
Итого, прямо со второй строчки вашего примера получаем ненужный (спорно и отключаемо, возможно он вам и нужен дальше для каких-то целей) и неоптимальный (бесспорно, это плохой запрос и общеизвестный антипаттерн) запрос к БД
Можно я не буду эту лажу воспроизводить?)
Срочно устраивайтесь в Databricks, а то они зачем-то Spark Dataframe API трансформируют на Spark SQL, а не наоборот, дилетанты!1! И всякие Iceberg, Hudi и другие профессиональные инструменты для работы с данными почему-то продолжают развиваться в парадигме SQL в первую очередь.
Ну и с прикладной стороны, по секрету скажу, куча "сверхсложной логики" по работе с данными в крупнейших банках и телеком-провайдерах написана в БД - это проще, производительнее, надёжнее
Если в вашем пузыре клепания CRUD-сайтиков никто не умеет в SQL на профессиональном уровне, это не значит, что он чем-то ограничен) Вполне себе Тьюринг-полный язык программирования
Осталось только понять зачем))
Данные хранятся вне приложения, строго типизированы вне приложения, ACID реализуется вне приложения, данные из БД легко выгружаются в нативные объекты языка (словари, кортежи, массивы, датафреймы...)
Логика кода от его обфускации в ORM или без него не должна меняться или становиться более или менее цельной
То же самое с рефакторингом, только SQL переписывать, тестировать и профилировать куда проще
Вопрос - зачем вообще делать маппинг отношений в объекты в приложении?)
Страшно представить, как какая-нибудь SQLAlchemy справится с разветвлённой иерархией ролей в PostgreSQL, когда она на джойнах нескольких таблиц и базовых DML-операциях начинает спотыкаться)
Даже не хочу знать)
Я принципиально не понимаю как кривую и функционально неполную абстракцию над кодом может быть проще поддерживать, чем чистый, максимально explicit код, тем более такой простой, как SQL)
Ну это ожидаемо)
К счастью, современные ОРМ уже залатали 99% дыр в безопасности, которыми они посвистывали ещё лет 5-7 назад. А сливы данных из-за такого отношения к инфобезу уже к ORM не относятся
Вот если б ORM делали бы вид, что ещё и ролевые модели в БД умеют генерировать, вот тогда б точно приехали))
P.S. завтра утром до ноута доберусь, может накидаю какие-то варианты, раз так сильно просите)
Господи, ну вы что, не представляете генерацию параметризованной SQL-лапши без ORM? Это ж просто строка, её можно вертеть как угодно через условия в переменных и if / циклы и т. д. Если не требуется джойнить managers - да просто не генерируй соответствующий кусок строки, и всё))
Нужно переиспользовать шаблон логики? Не беда, человечество давно придумало шаблонизаторы (Jinja, Twig и т.п.) и пользовательские функции на языках, встроенных в БД (что даёт не только более чистый и стабильный код и на стороне приложения, и на стороне базы, но ещё и более безопасный код - см. например security definer-функции в PostgreSQL).
Единственное, что действительно необходимо для работы с БД из приложения - драйвер для подключения к этой БД (примеры для Python - psycopg / asyncpg, cx-oracle, pyodbc и т.п.)
С телефона я сейчас печатать код не буду, 1 мая, увы, не за рабочим местом)
Но тут такой примитив, что даже ORM не должен налажать, наплодив n + 1 проблему, избыточные джойны и отбитые списки в where. Хотя я не уверен) Да и не факт, что вы сами знаете как этот запрос сейчас у вас фактически выполняется)
Тут не один запрос, а простейшая параметрическая кодогенерация. Это всегда решается на уровне приложения или процедурного языка (PL/SQL, T-SQL, PL/pgSQL). ORM для этого не обязателен, на любом языке программирования из коробки можно собрать такой же запрос, в т.ч. с защитой от SQL Injection
А где тег "вредные советы", "сарказм"?
Использование ORM и по смыслу (напиши мне SQL-запрос на основе команды на другом языке), и по качеству результата (ниже плинтуса) эквивалентно использованию ChatGPT для генерации SQL-запросов
Это стандартные объёмы транзакций небольшой-средней локальной платёжной системы. Или базы данных платформы с чатами / соцсети тоже не самого большого масштаба. Или телеметрии с датчиков крупного автопарка / завода
Ничего сверхъестественного в 2024 году в этом нет
Запретить погромистам менять структуру кода в новых версиях
Сломал обратную совместимость - к тебе выезжает Github-патруль и ломает палец
Так вижу
Это некорректная формулировка
Статистика собирается по 300 * default_statistics_target кортежам с такого же количества страниц. Т. е. , по дефолту, 300 * 100 = 30000 строк
И ещё default_statistics_target определяет количество корзин в гистограмме значений, тут без всякого множителя
См. комментарий в исходниках по поводу числа 300