LINUX.ORG.RU

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

 ,


0

6

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

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

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

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

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

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

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

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

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

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

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

А вот при попытке записать в SQL эти байты могут испортиться…

Не понимаю каким образом.

У вас в библиотеке для подключения к БД (условном libpq++) идет какое-то перекодирование?

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

выбрали наихудший - ибо 2 номера наворачивает логику - как приотизировать поля какие из 4 вариантов возможно и прочая хурма

При чём тут приоритезация? В карточке клиента два поля «Телефон1» и «Телефон2». Как при добавлении новости на ЛОР есть поля «Дополнительное изображение #0», «Дополнительное изображение #1», «Дополнительное изображение #2». Как думаешь, там три поля в базе или массив или дополнительная таблица?

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

вот для сохранения уровня дискиссии

всёж повторно рекомендую (повторно?) сломать мозг

по различию уровень представления и уровень приложения в старых теориях у Дейты ( там ещё уровень хранения - и как раз попытка изолировать абкакции )

имхо плодить поля(однородные) в отношении обычно худший вариант из возможных

тем более современный sql позволяет авто-паковать(распаковывать) однородности в одно поле"массив"

ваще чем больше кривых решений тем дороже квалифицированный труд :)

чуть чуть становится понятней тейк Croco

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

У вас в библиотеке для подключения к БД (условном libpq++) идет какое-то перекодирование?

Да, согласен, он просто не сохраняет.

Insert into table failed: ERROR: invalid byte sequence for encoding «UTF8»

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

ваще пример inode fs первоуниха

подсказывает решение

вот есть два поля телефонов - некоторого типа (хз чисто текст с нормализацией при внесении али просто raw с прелестями постобработки; али числа с паразитным ненулём в нужной степени :) )

для сохранения старых ошибок стоит добавить одно поле - «остальные номера» и там с разделителем(ТМ)(но лучше с завершителем) ноль и более телефонов**

с «постепенным» переходом к случаю

двух полей - номер

и второе поле остальные номера

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

Тут все-таки вопрос откуда в исходной строке внутри C++ного кода возьмутся некорректные UTF-8 последовательности. Либо это баг в коде, например, неправильная модификация строки, либо левые данные были получены без проверки из внешнего источника.

От обоих этих случаев, имхо, самодельные строки просто так не защитят.

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

При чём тут приоритезация

в смысле логики - в практике возможно 3 случая от 0 до 2 номеров

при размазывания на два поля 4 случая ; приводящая либо к багам либо к дополнительным преседания сводящим 2 случая 10 и 01 к случаю один-номер

ваще это хорошо что люди творят

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

Тут все-таки вопрос откуда в исходной строке внутри C++ного кода возьмутся некорректные UTF-8 последовательности. Либо это баг в коде, например, неправильная модификация строки, либо левые данные были получены без проверки из внешнего источника.

Я же написал. В С++ std::string это любая последовательность байтов, а не строка UTF-8. Там может быть строка в другой кодировке. Или вообще встроенная картинка в каком-нибудь формате. Багом оно становится только при записи в SQL.

Например, программа обрабатывает файлы. Имя файла в Linux может содержать любые байты кроме «/» и «\0». В std::string имя файла читается, а в SQL уже не всегда.

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

Я же написал. В С++ std::string это любая последовательность байтов, а не строка UTF-8. Там может быть строка в другой кодировке.

Просто так не может.

Вы свои исходники держите в UTF-8. В случае VC++ компилируетесь так, чтобы и в исполнимом файле все было в UTF-8, а под Linux-ом на эту тему и париться не нужно.

Следовательно в коде у вас не может быть текстовых строк вне UTF-8, если только вы:

  • не допустили ошибку при манипуляции своими строками;
  • не прочитали данные из внешнего источника без валидации.

Или вообще встроенная картинка в каком-нибудь формате.

Это означает проблему в вашем коде – вы смешиваете std::string-и с текстом с std::string-ами с бинарными данными.

В std::string имя файла читается, а в SQL уже не всегда.

Т.е. вы хотите сказать, что в Linux-е можно получить имя файла в некорректном UTF-8 представлении?

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

И в чем проблема? Если хочешь хранить бинарные данные, то храни их как бинарные. В том же постгресе это bytea, в прочих БД могут быть другие варианты.

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

Вы свои исходники держите в UTF-8. В случае VC++ компилируетесь так, чтобы и в исполнимом файле все было в UTF-8, а под Linux-ом на эту тему и париться не нужно.

При чём тут исходники? Большинство программ работают с внешними данными: файлами, именами файлов, байтами из Сети…

В UTF-8 гарантированно можно загнать только пользовательский ввод.

Это означает проблему в вашем коде – вы смешиваете std::string-и с текстом с std::string-ами с бинарными данными

В коде проблемы нет. Есть проблема записать std::string с бинарными данными в SQL.

Т.е. вы хотите сказать, что в Linux-е можно получить имя файла в некорректном UTF-8 представлении?

Конечно. Кодировка определяется пользователем, а не файловой системой.

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

В том же постгресе это bytea, в прочих БД могут быть другие варианты

И сразу же перестаёт работать индексация, насколько я понимаю.

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

При чём тут исходники? Большинство программ работают с внешними данными: файлами, именами файлов, байтами из Сети…

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

И если с данными внутри все OK при нормальной сборке проекта, то вопрос остается только с данными снаружи. Которые должны валидироваться, если мы имеем дело с текстом в UTF-8.

Есть проблема записать std::string с бинарными данными в SQL.

SQL-СУБД перестали поддерживать BLOB-ы?

Кодировка определяется пользователем, а не файловой системой.

Прекрасно. Допустим, ваша программа пишет логи в UTF-8 и должна записать туда имя этого файла. Или должна сформировать JSON с именем этого файла внутри.

Чем это отличается от записи в СУБД?

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

Которые должны валидироваться, если мы имеем дело с текстом в UTF-8.

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

SQL-СУБД перестали поддерживать BLOB-ы?

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

Допустим, ваша программа пишет логи в UTF-8 и должна записать туда имя этого файла.

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

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

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

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

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

Нет, можно делать индекс как по этому bytea, так и по expression (например, по decode этого индекса в utf-8 с replace инвалидных вещей). bytea — это буквально raw string для постгреса, есть ограничения только на локалеспецифичные операции (потому, что у массива байт нет локали).

С сортировкой сложнее, но сортировка мусора без кодировки это изначально не определенная операция. На практике можно сделать generated column с попыткой декодировать это все в нормальную юникодную строку (convert_from + decode с escape там) и сортировать по нему.

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

Постгрес умеет и индексы, и ключи, и поиск, но операциями для блобов (вроде position), а не для строк. Для локалеспецифичной сортировки нужно будет вытаскивать строку из блоба с либо игнором, либо escape/replace инвалидного юникода. Эту строку можно вытаскивать + сортировать в отдельный generated column либо на лету.

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

В С++ std::string это любая последовательность байтов

Для бинарных данных (которые в С++ по ошибке назвали «string») в sql надо использовать не типы вроде text, а типы вроде blob.

PolarFox ★★★★★
()

Его крокейшество не понимает, что главное в СУБД - это вовсе не SQL, а вещи вроде кластеризации, писания бэкапов, и вот этого всего. А в современное время - ещё и интеграция со всякими ZNS. И если ты начнёшь пилить все это самостоятельно, то получишь ту же СУБД. Только самопальную и вероятно с кучей багов и уязвимостей, которую тебе к тому же придётся самостоятельно поддерживать.

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

Ладно. Похоже, постгрес по сравнению с «обычным SQL» заметно продвинулся.

Посмотрел, действительно есть и подстроки из блоба и индексы по выражению.

А вы сможете сформулировать для постгреса запрос «получить все записи относящиеся к последним 5 дням, по которым есть хотя бы одна запись»?

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

И даже рациональные числа в постгрес, оказывается, есть.

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

а вещи вроде кластеризации, писания бэкапов, и вот этого всего. А в современное время - ещё и интеграция со всякими ZNS

Вот если всё это надо, то верно.

Столяров про ситуацию, когда ставишь себе локальное прикладное приложение, а оно себе постгрес хочет.

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

PGSQL

CREATE TABLE logs (id SERIAL DEFAULT, event_time TIMESTAMP NOT NULL, message VARCHAR(1024) NOT NULL);


WITH days AS (
  SELECT DISTINCT event_time::date AS day
  FROM logs
  WHERE message IS NOT NULL AND btrim(message) <> ''
  ORDER BY day DESC
  LIMIT 7
)
SELECT *
FROM logs
WHERE event_time::date IN (SELECT day FROM days)
ORDER BY event_time DESC;

MySQL

CREATE TABLE logs (id INT PRIMARY KEY, event_time TIMESTAMP NOT NULL, message VARCHAR(1024) NOT NULL);


SELECT *
FROM logs
WHERE DATE(event_time) IN (
    SELECT day
    FROM (
        SELECT DATE(event_time) AS day
        FROM logs
        WHERE message IS NOT NULL AND TRIM(message) <> ''
        GROUP BY DATE(event_time)
        ORDER BY day DESC
        LIMIT 7
    ) AS t
)
ORDER BY event_time DESC;
leave ★★★★★
()
Последнее исправление: leave (всего исправлений: 2)
Ответ на: комментарий от leave

Оптимизатор на SELECT DISTINCT event_time::date AS day ... ORDER BY day DESC LIMIT 7 сможет сообразить, что не надо читать всю таблицу?

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

Потому что «главное в СУБД - это вовсе не SQL, а вещи вроде кластеризации, писания бэкапов, и вот этого всего». А в локали оно всё не надо.

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

Мне просто было интересно как мои инструменты справятся с идентичной или аналогичной задачей. Мне ещё до сих пор не приходилось писать программу на C.

Хотя на Go приходилось разок, когда нужно было восстановить бэкап Windows 7. Я тогда не мог понять, что у меня текстовый редактор не поддерживает обработку нулевого байта и не всегда об этом кричит, поэтому от безысходности не мог найти другого выхода.

По поводу тормозных редакторов: zed обещает хорошую работу с большими файлами. Он там какую-то оптимизированную структуру данных использует. Сам не тестировал, но уже давно по-доброму завидую. У меня файлы в пару гигабайт открываются, но с ожиданием в полминуты.

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

ну ты бы duck db быб - оно ток мо локально бест в облахо есть другое (впрочем эквивалентное)

duckdb это реально вкусняшка

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

Если это одна и та же таблица, то просто запрос на «получить записи с датой >= сейчас - 5 дней и < сейчас» будет работать. «По которым есть хотя бы 1 запись» всегда TRUE для этих записей.

Если «по которым есть хотя бы одна запись» это отдельная таблица, то можно тем же WHERE EXISTS?

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

Если это одна и та же таблица, то просто запрос на «получить записи с датой >= сейчас - 5 дней и < сейчас» будет работать. «По которым есть хотя бы 1 запись» всегда TRUE для этих записей.

Нет. В таблице записи на 29.09, 26.09, 25.09, 23.09. А сейчас - 5 дней = 25.09.

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

не, ржавчина мне не нужна ни в каком виде. её у меня на машине нет и не будет. пусть ржавеют где-нибудь в другом месте :)

проблема открытия больших файлов в основном в мапировании, а не в «оптимизированных структурах».

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

проблема открытия больших файлов в основном в мапировании, а не в «оптимизированных структурах».

Проблема, что умение работать с данными, не помещающимися целиком в оперативную память, стало забытой технологией древних.

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

Умение работать с данными, которые помещаются в оперативную память — тоже утерянная технология.

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

скорее всего да, и это меня и удивляет. казалось бы, ничего сложного. ан-нет. на практике я вижу, что все редакторы пытаются зажрать весь файл в память. типа, виртуальной памяти много, давайте всё туда засунем.

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

я бы еще индекс на event_time докинул, конечно

Разумеется, предполагается, что индекс там есть.

The query optimizer takes LIMIT into account when generating query plans

Я про комбинацию с DISTINCT…

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

Столяров про ситуацию, когда ставишь себе локальное прикладное приложение, а оно себе постгрес хочет.

ни разу не видел, чтобы какое-то локальное приложение хотело себе постгрес. По ощущениям из тех, кому оно нужно, 95% промышляют sqlite. Вон тот же syncthing на него перешел. А sqlite ни пить ни есть не просит, лично у меня никогда с ним не было проблем.

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

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

Аконади в кедах вроде мускуль хочет.

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

ну вот akonadi. Либо mariadb, либо postgresql (опционально). Судя по репам арча, это единственное подобное. Я им никогда не пользовался, поэтому не знал. Все остальные с такой зависимостью - всякие серверные приложения, ну а на сервере иметь постгрес просто доктор прописал.

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

А.

CREATE TABLE logs (id SERIAL PRIMARY KEY, event_time TIMESTAMP NOT NULL, message TEXT NOT NULL);
CREATE INDEX logs_date ON logs(event_time);


INSERT INTO LOGS (event_time, message)
VALUES 
('2025-09-29', 'in range'), 
('2025-09-26', 'in range'),
('2025-09-25T01:00:00', 'in range'), 
('2025-09-09', 'out of range'),
('2025-09-25T02:00:00', 'in range'),
('2025-09-23', 'in range'),
('2025-09-22', 'in range');


WITH first_nonempty_date AS (
  SELECT day::timestamp AS day_ts FROM (
    SELECT DISTINCT event_time::date AS day
    FROM logs
    WHERE message IS NOT NULL AND btrim(message) <> ''
    ORDER BY day DESC
    LIMIT 5
  ) ORDER BY day ASC LIMIT 1
)
SELECT logs.*
FROM logs
JOIN first_nonempty_date ON TRUE
WHERE event_time >= first_nonempty_date.day_ts
ORDER BY event_time DESC;

Так?

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

Не, я помню ещё какая-то программулина была, которая требовала БД установленную. Только уже забыл, какая :)

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

Можно без докера запустить. Доступ к веб-интерфейсу через http://localhost.

К нему можно подключиться удалённо, если настроить сеть. Но с таким же успехом можно и к удалённому емаксу или вскоду подключиться, хотя это не веб-приложения.

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

Устанешь ты его кирпичики без докера собирать и потом обновлять и саппортить, ты смотрел, чего там в контейнере напихано?

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

Вроде, довольно простая установка. Но обновлять и саппортить не пробовал, что там в контейнере — не смотрел. Если это оно, то выглядит как немного.

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

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

https://kassa.bifit.ru/wiki/index.php?title=%D0%91%D0%98%D0%A4%D0%98%D0%A2_%D0%9A%D0%B0%D1%81%D1%81%D0%B0_Desktop_%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA_PostgreSQL

https://github.com/glondu/nurpawiki/blob/master/doc/Installation.md

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