Database First! О распространённых ошибках использования РСУБД / Николай Самохвалов (Postila)

  Рет қаралды 11,379

HighLoad Channel

HighLoad Channel

Күн бұрын

Приглашаем на конференцию HighLoad++ 2024, которая пройдет 2 и 3 декабря в Москве!
Программа, подробности и билеты по ссылке: clck.ru/3DD4yb
--------
РИТ++ 2017, HighLoad Junior
Тезисы:
junior.highload...
Любой Full Stack Developer сегодня обязан иметь в своём арсенале опыт и умение работы хотя бы с одной популярной РСУБД. Но без понимания основ - того, какие задачи решают СУБД, как происходит работа с данными, какие есть базовые возможности для этой работы, - такие умения превращаются в воздушный замок, быстро разрушающийся при росте проекта.
Этот доклад - попытка разбудить интерес слушателей к тщательному изучению основ теории и практики реляционных баз данных и к применению всей мощи РСУБД по прямому назначению.
...

Пікірлер: 34
@alzasr
@alzasr 5 жыл бұрын
Спасибо за доклад. Моё мнение: Согласен с тезисом "проверки должны быть как можно ближе к данным", но не согласен что все проверки должны быть в СУБД. Валидация данных - это часть бизнес логики, получается что бизнес логика размазывается с application layer на СУБД. Это минус, поскольку теперь бизнес логика находится ещё в одном месте, а она должна находится как можно более кучно. Кроме того, структура БД не версионируется, для версионирования приходится писать миграции с откатом. И если для структуры данных более менее всё понятно и уже устаканилось, то для хранимок и валидаторов всё сложнее. Усложняется переключение между разными версиями проекта. Любые проверки, независимо где они находятся, это процессорное время и память. Application layer масштабируется на раз, а DB layer, особенно мастернода, значительно сложнее (про это был последний вопрос, но из-за акцента на CSV докладчик не ответил на него). На многих слайдах, когда необходимо реализовать дополнительную функциональность (например админку), рисуется схема с прямым доступам к СУБД из допфункциональности, но ведь можно сделать программную прослойку с API, которая будет оперировать бизнес сущностями, таким образом изолировав потребителя от реализации хранения данных. Для реализации логики в СУБД нужно знать особенности СУБД, т.е. повышается требования к скилам программиста. Утверждение, что SQL легко читаем - ложно, много раз встречал десятиэтажные SQL запросы с подзапросами, которые очень сложно было понять, SQL - это язык, на нём можно писать ясно, а можно запутанно. Утверждение "db first" (сначала попробуй сделать на СУБД) это из лагеря DBA, если смотреть продукт в целом, нужно находить баланс. Переносить логику в СУБД нужно тогда, когда это оправдано. Ясно что реализовывать уникальные ключи средствами application layer неэффективно. Но и проверять что пользователь использует "достаточно сложный пароль" в СУБД не стоит. О переносе агрегации и фильтрации данных в СУБД решать нужно в каждом частном случае, ведь можно ускорить отдельный клиентский запрос (речь не про SQL запрос, а запрос в терминах бизнес задачи), но затормозить всю систему в целом.
@Ipat639
@Ipat639 Жыл бұрын
Этот коммент информативнее чем сам доклад😂, Добавлю ещё что докладчик предложил использовать адрес эл.почты в качестве первичного ключа, я с этим категорично не согласен, не учитывается возможный процесс где пользователь может свою эл.почту поменять. Первичные ключи всётаки должны быть абстрагированны от сущностей. Автору надо было сделать больший упор на 3нф и прочее
@DemiGoodUA
@DemiGoodUA Жыл бұрын
@@Ipat639 так же не понял любви автора к вещественным праймери ключам, ведь то что сегодня уникально завтра уже нет, прогнозировать развитие продукта наперед мы не можем
@denis-suleimanov
@denis-suleimanov 7 жыл бұрын
Когда пошли примеры - запись отвратная. На экране не видно ничего, сплошной засвет, а переключить вид на сплитскрин монтажник видать не догадался.
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
да, не очень вышло местами. вот слайды: www.dropbox.com/s/y0h6toonhpbd11h/DatabaseFirst_RIT_HLj_Samokhvalov.pdf?dl=0
@denis-suleimanov
@denis-suleimanov 7 жыл бұрын
Благодарю. Если можно, то задам вопрос: Вы в докладе несколько раз упоминаете хранимки, и, насколько я понял вашу философию отношения к БД и СУБД, хранимки это хорошо, это нужно юзать. Но ведь с ними столько проблем: от разделения логики между приложением и БД до версионирования и тестирования. Может быть посоветуете какие-то best practice как готовить хранимки? (Постгрес в приоритете)
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
Конечно. Xранимки - НЕ ЗЛО. Злом их принято считать традиционно, потому что они в некоторых популярных опенсорсных СУБД работали очень плохо. По вашим вопросам. Я пока вижу два пункта, про разделение логики и про «готовку» (версионировение, тестирование) 1) дело в том, что часть логики давно «перетащил» на себя фронтэнд (клиент стал толстым - мобилки, реакт и т.д.). Выходит, что всё равно приходится «париться» и разделять бизнес-логику. Толстого апп-слоя в архитектуре давно уже не существует как класса, это всё осталось в девяностых и нулевых. Так вот, мой тезис в том, что если вы заберёте всё, что можно забрать из так называемой «бизнес-логики» на фронт, то очень большой кусок из того, что остаётся, - это типичные задачи для СУБД. Валидация данных, поддержка их в согласованном виде и тд. В некоторых случаях можно пойти дальше и прибить (или почти прибить) app layer, раздербанив бизнес-логику на две части. Одна ушла во фронт (тут и спорить нечего, т.к. все так уже делают и кучу всего напридумывали, чтобы UX был лучше), а другую можно смело делать в самом Постгресе. SQL превосходен для работы с данными! Реально, в некоторых случаях вместо команды рубистов можно обойтись силами одного инженера с хорошим знанием SQL -- ставите PostgREST и всё делаете на хранимках, выходит быстро и качественно. API готов, можно сосредоточиться на приложении. Об этом я рассказывал на РИТ 2016, кстати. 2) Версионирование (принято называть "миграциями схемы БД"). Этому много уделено внимания было на наших встречах #RuPostgres. Посмотрите видео в канале RuPostgres, там была встреча в ЛАНИТ про liquibase и в Яндексе про их систему миграций. Сам использую sqitch.org и очень рекомендую. Легко встроить в любой стек. У рельсов ок использовать встроенную систему, с некоторыми оговорками. Насчёт тестирования. В sqitch встроены базовые возможности (verify-скрипты, см. доки на сайте, есть примеры). Я обычно делаю кучу тестов с помощью анонимных plpgsql-конструкций (do $$ blabla $$ language plpgsql;). Ещё есть целый фреймворк pgTap, автор тот же, что и у sqitch. Есть ещё куча вариантов писать миграции для БД. На хранимках уже тыщу лет работает скайп (мы авторов, кстати, привозили ещё году в 2008 на Highload, можно поискать материалы), и Яндекс.Почта мигрировала с Оракла на Постгрес очень успешно (см. доклады на #RuPostgres и PgCon), опять же во многом благодаря хранимкам и pl/proxy.
@denis-suleimanov
@denis-suleimanov 7 жыл бұрын
Благодарю за столь развернутый ответ.
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
Спасибо за отзывы, вопросы и плюсики! Слайды, если надо: www.dropbox.com/s/y0h6toonhpbd11h/DatabaseFirst_RIT_HLj_Samokhvalov.pdf?dl=1
@NikolaySamokhvalov
@NikolaySamokhvalov 2 жыл бұрын
Upd: docs.google.com/presentation/d/1rlNNFy-p-mlbJr3NJcFLMmJ0C81VE99kA_SZvJNFq5s/edit
@hakooplayplay3212
@hakooplayplay3212 4 жыл бұрын
мда... сначала когда были просто списки которые проговаривал автор - показывали слайды, а как пошли примеры кода - нет... где логика?
@GlebWritesCode
@GlebWritesCode 5 жыл бұрын
Интересный подход. Какие проекты применяют его на практике?
@coraxster
@coraxster 7 жыл бұрын
Как этот sql на 50 строк тестировать?
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
Как обычно, в CI. pgTap, sqitch / verify, анонимные конструкции do $$ ... $$ language plpgsql, в них используйте assert с продуманными сообщениями.
@asvitin
@asvitin 7 жыл бұрын
Хорошее выступление. Спасибо. Есть некоторые 1) Предлагаемое решение второго примера может быть получше WITH ordered_weather AS ( SELECT id , year , month , created , weather_is_fine , MIN(created) OVER(PARTITION BY year, month) AS min_created , ROW_NUMBER() OVER(PARTITION BY year, month ORDER BY id DESC) AS rn FROM Moscow_weather ) SELECT id , year , month , min_created AS created , weather_is_fine FROM ordered_weather WHERE rn = 1; 2) На мой вгляд проверки должны быть не только возле слоя хранения данных. Должно быть 3 уровня проверок. 2.1 Простые на самом раннем этапе(как можно ближе к входным параметрам) 2.2 Любые по сложности во время обработке на среднем слое. В простых случаях их можно не реализовывать 2.3 Не сложные в виде ограничений целостности на уровне БД возле самих данных. Триггера нельзя применять(ибо это одно из самых больших бед в БД), т.е. сложные проверки отметаются. Им только на среднем слое место.
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
Спасибо за отзыв! По пунктам. С первым согласен - да, оконными функциями в данном случае получается лаконичнее, чем плясками с массивами! Со вторым - ну что тут скажешь, основную мысль доклада, выходит, не полностью донёс. "Триггера нельзя применять(ибо это одно из самых больших бед в БД)" - это заблуждение. Расскажите это тем, кто пишет какие-нибудь серьёзные вещи. Например, АБСки (банковские системы).
@asvitin
@asvitin 7 жыл бұрын
Николай, благодарю за ответ! Мне кажется, что я писал достаточно серьезные вещи (работал с базами крупнейшего сотового оператора СНГ и крупнейшего ритейлера России), в высоконагруженной среде и достаточно большими объемами данных(100 Тб+). Как-то я занимался детальным анализом производительности системы, в которой на ключевой сущности, состоящей из мастер таблицы и таблицы деталей(100+ млд строк), сумарно было создано около 50 триггеров, некоторые из которых по 1500+ строк кода. Помимо анализа кода, профилировки, трассировки, я делал различные эксперементы замеряя на сколько меняется производительность типовых операций с таблицами от наличия индесков, контрейнтов и триггеров. Триггеры - вне конкуренции по влиянию на производительность. На низком уровне, даже идеально написанные построчные Триггера вынуждены проводить для каждой строки некоторое перключение контекста выполнения(проверял на Оракле, но я не представляю как эту особенность обойти), это значительно сокращает производительность batch обработки(наподобие INSERT SELECT, UPDATE многих строк, MERGE, DELETE многих строк). Ситуация становиться хуже, если триггера не идеально написаны. Я вкусил триггерный ад по полной и, думаю, что представляю, о чем говорю. Некоторые мои коллеги пришли из банкоской сферы(разрабатывали АБС) и их мнение полностью совпадало с моим по поводу триггеров. Я всецело поддерживаю наличие слоя храннимых процедур, где идеально размещать логику работы с (большими) масивами данных, и инкапулировать обращения к БД, скрывая детали реализации. Я полностью "за" наличие как можно большего числа ограничений целостноти на БД (они не только данные выверяют, но и помогают оптимизатору), но вот с триггерами ни как не могу подружиться. Извиняюсь, за дискуссию. Но именно в ней, вроде как, должна зарождаться истина. :) Еще раз спасибо за выступление!
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
Алексей Свитин «Как-то я занимался детальным анализом производительности системы...» А как именно вы оценивали вклад триггеров? Интересно, что с чем сравнивали
@asvitin
@asvitin 7 жыл бұрын
1. Трассировка. По трейсам видно сколько времени уходит на выполнение тех или иных запросов в рамках триггеров, а сколько на саму операцию модификации строки. Анализировал трейсы через OraSRP. 2. Профилировка. По ней можно понять сколько времени каждая строка PL/SQL кода выполнялась. Имея итоговое время выполнения запроса можно посчитать влияние триггера. Использовал самописные запросы для анализа HProfiler таблиц. Ничего нормального в сети на тот момент не нашел. 3. Созавал много копий идентичных структур с одинаковым набором данных. Затем накидывал FK, индексы, констренты, триггера в разных комбинациях на эти копии. И проводил тесты построчной вставки (с включенной и выключенной FOR оптимизацией), BULK вставки, обновлений и удалений. Но основной упор был на вставку, так как там основная логика. Разница с триггерами и без была настолько огромной, что сама операция размещения стоки в таблице составляла ничтожную долю процента относительно общего времени выполнения. Если бы вместо триггеров использовалась пакетная обработка(вставка идет именно блоками данных) через хранимки( у того же Оракла с этим все очень хорошо), и логика была бы разделена( а не смешана в триггеры на все случаи жизни) то по моему скромному мнению, производительность была значительно выше. Но уйти от триггеров, когда их много и основная логика в них , это очень сложная задача.
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
Ну надо смотреть, конечно, что конкретно в тех триггерах было. На мой взгляд, метка «триггеры=зло» это то же самое, что и «транзакции=зло». Давайте переформулируем. «Длинные транзакции - зло» и «долгие триггеры - зло». Интересно, конечно, какой оверхед на инсёрт даёт триггер-пустышка в Оракле. Для постгреса я по-быстрому проверил, вышло в районе 6%: Ок, у нас есть некоторый триггер, который что-то делает с данными. 6% оверхед на то, что он просто существует. Плюс какой-то (скорее всего бОльший) оверхед, если он что-то ещё и по правде делает. Конечно, особенно, если при этом участвуют другие таблицы. Теперь мысленно представим, что мы делаем то же самое, но на уровне приложения. Вот тут кроится забавное - очень часто разработчики делают операции с данными намного менее оптимально, чем если бы это было в триггере. СУБД относительно мало что стоит прогуляться за данными в какой-нибудь индекс. Или пересчитать данные у себя. В случае слоя приложения очего легко наступить на грабли сетевой сложности. Мой основной тезис в том, что надо сначала рассматривать работу ближе к данным. Нет, не всегда. Но ОЧЕНЬ часто. Нужно анализировать, конечно. Кроме того, если вам нужно быстро провести транзакцию, ну закиньте задание в отдельную таблицу и разгребайте её асинхронно (с помощью "select ... for update skip locked" это делается очень эффективно в несколько потоков). Асинхронные транзакции в Оракле тоже помогают такие схемы иметь, а сегодня вот в Постгрес 11 закоммитили (ура!) www.postgresql.org/message-id/E1edcRB-0004zs-B6@gemulon.postgresql.org И ещё. Вы правильно отмечаете, что часто нужно батчами работу вести для эффективности. Верно. Только это ж никак не конфликтует с работой на стороне СУБД и триггерами. Наоборот. Для этого есть statement-based triggers, правда, работать с ними можно стало нормально только недавно, с 10ки, когда добавили transition tables www.depesz.com/2017/06/02/waiting-for-postgresql-10-implement-syntax-for-transition-tables-in-after-triggers/ > Если бы вместо триггеров использовалась пакетная обработка похоже, на это ответил предыдущим абзацем > и логика была бы разделена( а не смешана в триггеры на все случаи жизни) а вот тут не очень понимаю. Наверное, речь про пакеты ? Это, конечно, очень многие просят - на юзервойсе тема номер 1 postgresql.uservoice.com/forums/21853-general
@michaelpetrov4965
@michaelpetrov4965 3 жыл бұрын
Доклад интересный, хоть и не со всем согласен. Но показывать оратора, когда обсуждают код на слайдах - минус.
@wolazant
@wolazant 7 жыл бұрын
Николай упоминал в докладе pdf'ку на 200 страниц, видимо с презентацией, где её можно посмотреть?
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
а не напомните контекст?
@NikolaySamokhvalov
@NikolaySamokhvalov 6 жыл бұрын
www.slideshare.net/samokhvalov/database-first, www.pgcon.org/2013/schedule/attachments/269_tour-of-postgresql-data-types.pdf andreas.scherbaum.la/writings/Tour_de_Data_Types_-_FOSDEM_2017.pdf
@rogozhka-racing
@rogozhka-racing 7 жыл бұрын
Нежелание паковать логику в БД не от недоверия и не потому что MySQL плохой, а потому, что архитектура в вебе может измениться моментально(в т.ч. от нагрузки изменившейся на 2 порядка) и слоника придется попросить на выход, как бы хорошо не справлялся с целостностью данных. На замену кластер из микросервисов с логикой в коде нормальных языков, с покрытием тестами и дебагом, а не логикой в суррогатных языках хранимок и ограничений таблиц.
@NikolaySamokhvalov
@NikolaySamokhvalov 7 жыл бұрын
Всё смешалось. Написано почти без грамматических ошибок, но логика не прослеживается, какой-то клубок мыслей. Кто сказал, что между целостностью и микросервисами надо выбирать что-то одно? Смотрите на опыт Zalando, было много на Highload. Кстати, советовать всем подряд микросервисную архитектуру - медвежья услуга, послушайте внимательно тех же Zalando. Далее, кто сказал, что тестами не нужно покрывать хранимки? Sqitch, pgTap или же любой ваш любимый фреймворк + анонимный plpgsql-код (do $$ ... $$ language plpgsql) и всё уезжает в CI. Дебаг - есть дебаггер для pl/pgsql, но честно, когда вы последний раз пользовались именно дебаггером, а не принтлайнингом для вашего любимого python/ruby/java/php? Строгая схема (там, где есть возможность её задать), ограничения целостности и хранимки - не враги, а помощники для быстрорастущего проекта.
@Петр-ч8л
@Петр-ч8л 2 жыл бұрын
Просто у многих на sql мозгов не хватает. Когда у тебя 10и этажные запросы, в голове очень сложно уложить такие выборки. И начинается всякая хрень типа Орм, nosql и прочей дичи
@Ipat639
@Ipat639 Жыл бұрын
Так вот кто сделал МирТесен из которого невозможно выйти и заспамил почту, прям жесть была, не делайте так)
@02krysnik
@02krysnik 2 жыл бұрын
русский Ричард Хендрикс )
@vladimirgrishin290
@vladimirgrishin290 4 жыл бұрын
масиквел!
@troepolik
@troepolik 4 жыл бұрын
какие-то баяны нарассказывал...
Une nouvelle voiture pour Noël 🥹
00:28
Nicocapone
Рет қаралды 9 МЛН
She made herself an ear of corn from his marmalade candies🌽🌽🌽
00:38
Valja & Maxim Family
Рет қаралды 18 МЛН
Гениальное изобретение из обычного стаканчика!
00:31
Лютая физика | Олимпиадная физика
Рет қаралды 4,8 МЛН
Лучший Гайд по Kafka для Начинающих За 1 Час
1:15:01
Une nouvelle voiture pour Noël 🥹
00:28
Nicocapone
Рет қаралды 9 МЛН