LINUX.ORG.RU

Его крокейшество о вредности СУБД, если архитектурно она для программ, а не живого человека

 ,


0

6

Давно уже что-то про Столярова Croco ничего не было =) А тут он повод недавно дал, расписав почему считает недопустимым использовать СУБД в архитектуре при проектировании софта. То есть, если для каких-то программ нужно хранение данных, его надо индивидуально под программу делать, а не подключать базы данных.

Можно обсудить. В принципе я сам не люблю для локальных данных применять базы данных, часто достаточно просто текстовых файлов и это даже надежно и быстро. Но в целом каким-то луддизмом отдает. Его сообщение ниже:

http://www.stolyarov.info/guestbook#cmt97

==============

Я придерживаюсь принципа несколько более узкого: недопустимо создание, распространение и использовние программ, для работы которых требуется СУБД.

Причины можно назвать, например, такие:

  1. СУБД — это лишняя внешняя зависимость, при том что вообще любые внешние зависимости суть хамство в отношении пользователей и мейнтейнеров;
  2. СУБД требует трудозатрат на установку, настройку и дальнейшее администрирование;
  3. СУБД способна упасть (и да, падает намного чаще, чем, скажем, тот же апач — вообще пока мои сайты жили на «традиционной» CMSке, именно СУБД была причиной всех случаев downtime моих сайтов, за исключением одного, когда на сервере физически осыпался жёсткий диск);
  4. СУБД требует от пользователя постоянно обновлять навыки, которые, возможно, больше ни для чего не нужны;
  5. СУБД хранит информацию пользователя в неочевидном для него виде; этим грешат не только СУБД, конечно, но СУБД мало того что хранят всё в бинарных файлах, которые без самой СУБД даже думать нечего разобрать, они ещё и вводят дополнительный слой хаотизации в виде схемы БД, провоцируя разработчиков софта на внедрение «решений», единственное «описание» которых остаётся в голове у автора;
  6. СУБД требует изрядных вычислительных мощностей и крадёт (а вовсе не повышает, как почему-то многие уверены) производительность.

Я, заметим, не рискну утверждать, что СУБД как сущность вообще никогда не может ни для чего применяться. Тут вопрос в том, кто на ком стоял: если главной целью является база данных как таковая, то есть вот имеется какой-то значительный объём разнородной, но при этом взаимосвязанной информации и стоит задача обеспечить его хранение и в нём поиск, причём никто заранее не знает, какие именно задачи будут решаться на этом массиве информации, какие именно поисковые запросы будут делаться и вот это вот всё, то да, СУБД вполне может оказаться адекватным решением, и даже для работы с ней могут создаваться вспомогательные программки. Это, конечно, не оправдывает существования языка SQL, который в любых его проявлениях представляет собой надругательство над здравым смыслом, но в целом СУБД как вид софта существовать, наверное, всё-таки может — но лишь в случаях, когда либо вообще нет никаких программ кроме неё самой, либо программы делаются для неё, а не она сама поддерживается для работы какой-то программы.

Всё это можно выразить и короче: СУБД, по-видимому, вполне имеет право на существование в ситуации, когда основным способом работы с ней будет непосредственное вбивание запросов на её языке запросов живым человеком. То есть когда именно вот это — основное, а всё остальное вспомогательное. В подавляющем большинстве случаев мы видим прямо противоположное: с СУБД как-то там общается некая программа (намного реже — больше одной программы, и это уже пограничный случай), а живой человек делает запросы либо только в рамках обслуживания всей системы, либо вообще никогда.

Когда же пишется некая программа, предполагающая применение для конкретных задач (а программы иначе, собственно, и не пишутся), и данные возникают исходя из этих задач, а не наоборот, то за саму идею задействования внешней СУБД нужно убивать на месте. Сугубо из санитарных соображений.

★★★★★
Ответ на: комментарий от pekmop1024

Да не, он довольно быстро и легко обновляться из репы, если не запускать. Если запустил → начнутся пляски с последовательным обновлением по версиям.

Zhbert ★★★★★
()
Ответ на: комментарий от x3al

Да. И дальше вопрос, сможет ли оптимизатор сообразить SELECT DISTINCT ... ORDER BY day DESC LIMIT 5 сделать, не читая всю таблицу (скажем, там 200ГБ, а за последние 5 дней всего мегабайт).

Для своей структуры хранения алгоритм тривиальный.

monk ★★★★★
()
Ответ на: комментарий от monk

И которые по сути задачи не обязаны быть текстом.

Тут нужно определиться:

  • у нас есть std::string, которые хранят текст. Этот текст мы храним, например, в UTF-8. И, соответственно, валидируем, где нужно, входящие данные. Такие вещи мы отображаем в БД через varchar или что там есть еще в конкретной СУБД;
  • у нас есть std::string, которые хранят бинарные данные. Соответственно, отображаем их в БД как BLOB-ы.

Задача программиста делать так, чтобы одни std::string не перепутались с другими. Например, посредством какого-то из вариантов самодельных strong typedef.

Для BLOB’ов SQL не умеет ни сортировку, ни индексы ни внешние ключи…

Тут ниже уже ситуацию прояснили более знающие люди. Но я другого не пойму: если у вас бинарные данные (например, видео-кадры или фрагменты аудио-потока), то зачем их сортировать, индексировать и т.д.?

Если логи ограничены UTF-8, то имя будет закодировано в какой-нибудь base64.

base64 нечитабельна для человека. Удобнее символы, которые не могут быть представлены в UTF-8/ASCII, оформлять в виде escape-последовательностей.

Ну и заодно:

Но логи обычно не ограничивают какой-то кодировкой (я такого не видел).

Если вы не ведете логи в бинарном виде, то логично писать логи в том виде, в котором текст представляется в программе. Насколько я могу судить, в большинстве случаев сейчас это UTF-8. Но под Windows доводилось видеть и в UCS-2 (или как там сейчас правильно виндовый двубайтовых Unicode называется).

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Тут ниже уже ситуацию прояснили более знающие люди. Но я другого не пойму: если у вас бинарные данные (например, видео-кадры или фрагменты аудио-потока), то зачем их сортировать, индексировать и т.д.?

У меня «бинарные данные» имена файлов, например. Их надо как-то сортировать для обработки (например, чтобы можно было продолжить обрабатывать после перезапуска). А ещё по имени файла может быть список тэгов, то есть это имя должно быть первичным/внешним ключом.

Насколько я могу судить, в большинстве случаев сейчас это UTF-8.

В большинстве. Но попадаются в текстовых логах и koi8 и iso8859. Текстовый лог не падает и vim’ом читается.

monk ★★★★★
()
Ответ на: комментарий от monk

У меня «бинарные данные» имена файлов, например.

Имена файлов в которых есть не-ASCII и не Unicode-символы? Аху***ть!

ССЗБ

Но зачем?

Их надо как-то сортировать для обработки (например, чтобы можно было продолжить обрабатывать после перезапуска).

Разные варианте escaping-а (хоть С-шный, хоть percent encoding из URL) должен был бы спасти отца русской демократии.

eao197 ★★★★★
()
Ответ на: комментарий от monk

Сорян, я в плейграунде проверял корректность запросов, которые писал из головы. Надо проверять на живой базе, а мне откровенно лень сейчас, равно как и курить доки по внутряне постгри.

leave ★★★★★
()
Ответ на: комментарий от eao197

Имена файлов в которых есть не-ASCII и не Unicode-символы? Аху***ть!

Имена файлов в koi8 (копия каталога со старого диска 25-летней давности), имена файлов в cp1251 (с ASPLinux) …

И все программы, с которыми я туда лазил, с ними вполне успешно работают (матерятся в консоли на ошибки конвертации, рисуют квадратики в списке файлов, но открывают).

Разные варианте escaping-а (хоть С-шный, хоть percent encoding из URL) должен был бы спасти отца русской демократии.

Я не спорю. Просто пример структуры, которая в SQL без обработки не ложится.

monk ★★★★★
()
Ответ на: комментарий от Zhbert

Да не, он довольно быстро и легко обновляться из репы, если не запускать. Если запустил → начнутся пляски с последовательным обновлением по версиям.

Поэтому проще и правильне использовать контейнер. Его и обновлять можно без плясок с бубном. Постгрю особенно если использовать внешнюю. Тащемта у меня есть эксперимент: Gitlab CE, который висит на автообновлении в Watchtower. Больше полугода уже висит, обновляется себе, кушать не просит.

pekmop1024 ★★★★★
()
Ответ на: комментарий от monk

Просто пример структуры, которая в SQL без обработки не ложится.

Я думаю, что описанные вами случаи будут вести к проблемам не только в случае с SQL.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Я думаю, что описанные вами случаи будут вести к проблемам не только в случае с SQL.

Вряд ли. В gtk работают, в vim работают, в bash работают.

monk ★★★★★
()
Ответ на: комментарий от Iron_Bug

не, ржавчина мне не нужна ни в каком виде

А почему нет? Общеизвестные причины мне известны, но может есть что-то ещё.

Мне самому не нравится повсеместное пихание раста, но дело же не только в языке, это прежде всего сложный интеллектуальный продукт.

kaldeon
()
Ответ на: комментарий от monk

В gtk работают, в vim работают, в bash работают.

Оно, как я понимаю, работает на открытие/изменение самого файла.

А когда вы попробуете это имя отдать в json-ое в каком нибудь REST-ответе?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

А когда вы попробуете это имя отдать в json-ое в каком нибудь REST-ответе?

А ему не всё равно на поток байтов между кавычками?

А когда совсем не всё равно, недавно в 1С на грабли наступили: у них строки (и вообще все объекты) между клиентом и сервером передаются в XML. Всё было хорошо, пока Честный знак не придумал в штрихкоде разделителем ставить 0x1D, который запрещён в XML. Стали штрихкоды перед каждым серверным вызовом в base64 заворачивать…

monk ★★★★★
()
Ответ на: комментарий от monk

А ему не всё равно на поток байтов между кавычками?

Полагаю, что нет.

https://www.ietf.org/rfc/rfc4627.txt

3.  Encoding

   JSON text SHALL be encoded in Unicode.  The default encoding is
   UTF-8.

   Since the first two characters of a JSON text will always be ASCII
   characters [RFC0020], it is possible to determine whether an octet
   stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
   at the pattern of nulls in the first four octets.

           00 00 00 xx  UTF-32BE
           00 xx 00 xx  UTF-16BE
           xx 00 00 00  UTF-32LE
           xx 00 xx 00  UTF-16LE
           xx xx xx xx  UTF-8
eao197 ★★★★★
()
Ответ на: комментарий от eao197

Прикольно, если не та кодировка, jq молча портит строку:

$ echo '{"тест": 0}' | iconv -t koi8-r | jq . | iconv -f koi8-r
{
  "О©╫О©╫О©╫О©╫": 0
}
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Прикольно, если не та кодировка, jq молча портит строку:

ЕМНИП, есть некое неформальное (а может и формальное?) соглашение о том, что если при декодировании UTF-8 встречается нелегальная для UTF-8 последовательность, то она заменяется каким-то специальным символом (правда его код я уже за давностью лет забыл).

eao197 ★★★★★
()
Ответ на: комментарий от kaldeon

я думаю, «общеизвестных» вполне хватает. моя позиция такова, что это поделка проприе-растов и копро-растов. несмотря на то, что они там это маскировали под «открытое и народное», но хрена лысого. это поделка конкретно Мозиллы и её ещё поддерживает Гугл. сделано с целью вытеснить открытые бесплатные реализации и насадить свои решения. как обычно у копрорастов. поводы для насаждения (якобы «безопасность» и фальшивое «удобство») высосаны из пальца. собственно говоря, эталонное ненужно. но в рекламу этого ненужно среди школотронов копрорасты ввалили довольно много денег.

Iron_Bug ★★★★★
()
Последнее исправление: Iron_Bug (всего исправлений: 1)
Ответ на: комментарий от necromant

а утилита html2text за какое количество времени справилась, не измеряли случаем?

Нет. Не измерял. Уже себя ограничиваю в этом маленьком проекте, хочется, конечно, еще померить и графики построить. Но пока ставлю на паузу.

lbvf50txt
()
Ответ на: комментарий от monk

Т.е. ваш генератор XML не умеет обеспечивать well-formed XML и заменять символы на entities? Уж не конкатенаций ли строк вы XML формируете?

Begemoth ★★★★★
()
Ответ на: комментарий от PolarFox

Если у сервера 32 ядра, то это около 32 запросов в секунду до того как скорость и этого запроса, и всего остального что происходит на этом сервере начнёт деградировать.

Многопоточность это интересная тема. Досконально разобраться как писать код который действительно ускоряет работу программы за счёт параллельного исполнения. Ведь надо, чтоб задача изолирована в памяти без обращения к внешним устройствам: сети или диску.

В Golang есть отдельный скедулер который может быстро перещелкивать горутины прикрепляя и открепляя их от треда ОС. Таким образом быстро перебираются корутины ожидающие ответа из сети. И сокращается время на скачивания данных из нескольких источников, так как этот процесс «запаралеливается», а цена переключения - минимальна.

Вот тут уже надо копать в глубь с буферам и интерфейсами. На каком этапе ОС сигнализирует корутине что пришли данные из сети? И так далее и тому подобное. Это уже достаточно низкий уровень, который не так часто нужен для проектирования конечных приложений.

Например, сайт codewars.com около 10 лет назад вообще работал на NodeJS c его Eventloop и без доступа к такому глубокому уровню детализации. Читал код запуска задачу на проверку в отдельном контейнере.

Так что так.

Concurrency is the computer science term for breaking up a single process into independent components and specifying how these components safely share data. (c) Jonathan Bodner

Learning Go An Idiomatic Approach to Real-World Go Programming

page 203. Chapter 10. Concurrency in Go

Канкаренси это термин из информатики описывающий разбиение процесса на независимые компоненты и определение безопасного разделения данных между ними. (с) Джонатан Боднер

Есть о чем порассуждать.

lbvf50txt
()
Последнее исправление: lbvf50txt (всего исправлений: 2)
Ответ на: комментарий от lbvf50txt

Ведь надо, чтоб задача изолирована в памяти без обращения к внешним устройствам: сети или диску.

Это только вершина айсберга. Довольно быстро вы поймёте что «драться» за локальную память тоже дорого, а в некоторых случаях - и за cachelines тоже, даже при отсутствии явных зависимостей.

bugfixer ★★★★★
()
Ответ на: комментарий от monk

Это index-only запрос, оптимизатор не должен читать таблицу вообще. Если индекс хранится в нужном порядке, то и индекс не будет читаться целиком.

x3al ★★★★★
()
Ответ на: комментарий от x3al

Это index-only запрос

Пойду проверю.

На первый взгляд вы тут не попадете в индексы, потому что строите их на timestamp поле, а выбираете distinct с приведением к типу ::date - вроде бы не должно так работать.

Toxo2 ★★★★
()
Последнее исправление: Toxo2 (всего исправлений: 1)
Ответ на: комментарий от PolarFox

От БД, возможно, зависит.

Может и зависит.

В PostgreSQL 17.5 - тут Bitmap Index Scan со сканированием всех строк. Что вполне понятно.

Но может в каких-то других БД есть особая магия.

Toxo2 ★★★★
()
Ответ на: комментарий от Toxo2

Если все поля в запросе есть в индексе (а в индекс можно включить в том числе и условия вроде WHERE message IS NOT NULL AND btrim(message) <> ''), то планировщик должен его использовать практически всегда если не считает, что в таблице буквально 3 строки и проще сделать full scan.

Можно сделать индекс по ::date.

DISTINCT применяется после индекса, поэтому не должен влиять.

x3al ★★★★★
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)