Отчасти это действенный совет, отчасти — вопрос к читателям.

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

Почему не sqlite?

sqlite — достаточно неплохая база данных, но данные хранятся в одном файле.

Из этого следует, что, каким бы ни было ваше приложение, оно работает на одной и только на одной машине. Или, по крайней мере, в одной общей файловой системе.

Если вы создаёте десктопное или мобильное приложение, то это идеальное решение. Если вы делаете веб-сайт, то это не всегда так.

Существует множество историй успеха о применении sqlite для веб-сайта, но в основном их рассказывают люди, создававшие собственные серверы и инфраструктуру. Platforms as a service наподобие Heroku, Railway, Render и так далее в общем случае ожидают, что вы будете использовать базу данных, доступ к которой выполняется через границу сети. Нет ничего плохого в том, чтобы отказаться от части преимуществ таких платформ, но подумайте, стоят ли преимущества sqlite отказа от предоставляемых платформой автоматических бэкапов баз данных и возможности работы с несколькими серверами приложений.

В официальной документации есть хорошее руководство с более подробным описанием.

Почему не DynamoDB, Cassandra или MongoDB?

Где бы ни был сейчас Рик Хулихэн, надеюсь, у него всё хорошо.

Я смотрю много докладов с конференций, но, вероятно, чаще всего смотрю его доклад DynamoDB Deep Dive 2018 года. Знаю, что немногие из вас готовы смотреть часовой доклад, но оно того стоит. Доклад очень хорош.

В целом смысл этого доклада заключается в том, что базы данных в том же стиле, что и DynamoDB (в том числе и Cassandra с MongoDB), замечательные, если... и это «если» очень важно:

  • Вы точно заранее знаете, что должно делать ваше приложение.

  • Вы точно заранее знаете, какими будут паттерны доступа.

  • Вам точно известно, что придётся масштабироваться до очень больших объёмов данных.

  • Вы готовы отказаться от определённого уровня consistency.

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

Какие бы запросы вам ни нужно было выполнять, перед хранением данных придётся закодировать это знание в один из таких индексов. Хотите хранить пользователей и искать их или по имени, или по фамилии? Тогда вам лучше создать ключ сортировки вида <FIRST NAME>$<LAST NAME>. Паттерны доступа должны быть неразрывно связаны с тем, как вы храните данные. Если паттерны доступа существенно изменятся, то может потребоваться полная повторная обработка всех данных.

И это раздражает, особенно в случае MongoDB, ведь разработчиков убеждают, что эта база данных более «гибкая». Да, вам не придётся создавать её схему. Да, можно просто сохранять нетипизированый JSON в коллекции. Нет, это не гибкий тип базы данных, а эффективный.

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

К тому же она не так удобна, если вам нужно выполнять аналитические запросы. На произвольные вопросы наподобие «сколько пользователей выполняло вход в прошлом месяце?» можно элементарно ответить, написав SQL-запрос; может быть, на реплике для чтения, если вы опасаетесь выполнять затратный запрос на той же машине, что работает с трафиком пользователей. Это просто невозможно для подобного типа баз данных. Для обработки данных вам потребуется вывести их с помощью ETL.

Если вы видите, что студент или выпускник использует MongoDB, то остановите его. Ему нужна помощь. Его ввели в заблуждение.

Почему не Valkey?

Ставшая потомком Redis, эта база данных больше всего известна тем, что работает эффективным кэшем вне процесса. Вы вычисляете что-то затратное один раз и засовываете это в Valkey, чтобы пяти вашим HTTP-серверам не приходилось вычислять это заново.

Однако её можно использовать в качестве основной базы данных. Она хранит все свои данные в ОЗУ, поэтому довольно быстра.

Очевидные проблемы:

  • Размер ОЗУ ограничен. Да, можно установить гораздо больше памяти, чем вы могли бы представить, но она всё равно достаточно ограничена по сравнению с жёсткими дисками.

  • Аналогично с DynamoDB и подобными ей базами данных, вам нужно будет заранее продумывать модель данных.

Почему не Datomic?

Если вы о ней уже знали, то заслуживаете уважения.

Datomic — это база данных NoSQL, но реляционная. У неё нет проблем, связанных с необходимостью проектировать всё заранее, к тому же она обладает некоторыми приятными свойствами.

Данные хранятся не в таблицах, а в парах «сущность-атрибут-значение-время» (entity-attribute-value-time, EAVT). Вместо строки person с idname и age мы храним 1 :person/name "Beth" и 1 :person/age 30. Благодаря этому запросы работают на основе «универсальных» индексов.

Вам не нужно координироваться с writer при отправке запросов. Запросы к базе данных выполняются по состоянию на заданное время. Новые данные, даже операции удаления (или, как их называют, retraction), на самом деле не удаляют старые данные.

Но существуют и серьёзные проблемы:

  • Она работает только с JVM-языками.

  • Вне Clojure (достаточно нишевого языка) её API ужасен.

  • Если плохо структурировать запрос, то сообщения об ошибках будут ужасными.

  • Вся вселенная разработанных для SQL инструментов здесь просто недоступна.

Почему не XTDB?

Любители Clojure создают множество баз данных.

По духу XTDB похожа на Datomic, но:

  • У неё есть HTTP API, то есть вы не привязаны к JVM.

  • Существует две оси времени, относительно которых можно выполнять запросы. System Time, когда записи были вставлены, и Valid Time.

  • Она имеет SQL API.

Самые важные аргументы против:

  • Она новая. Её SQL API появилась только в прошлом году. Недавно у неё поменялась вся модель хранения. Выживет ли разрабатывающая её компания ещё десять лет? Кто знает!

Ладно, признаю, это только один аргумент. Уверен, что можно придумать и другие, но считайте, что он актуален для всех новых баз данных. Лучший показатель того, что нечто будет существовать в будущем — это его возраст. COBOL существует уже десятки лет и будет жить ещё несколько десятков.

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

Почему не Kafka?

Kafka — это журнал, в который можно только добавлять информацию. Он может справляться с терабайтами данных. Это очень хороший журнал только для записи. Он превосходно работает, если вам нужно выполнять что-то наподобие event sourcing с данными, поступающими из множества сервисов, поддерживаемых различными командами.

Но:

  • До определённого масштаба таблица в Postgres идеально работает в качестве журнала только для записи.

  • Вероятно, над вашим продуктом не будут работать сотни людей и в него не будут поступать терабайты событий.

  • При создании Kafka consumer можно совершить больше ошибок, чем вы ожидаете, ведь вам нужно отслеживать своё место в журнале.

  • Даже если она имеет поддержку поставщика облачных услуг (а хорошие управляемые сервисы Kafka существуют), это ещё одна часть инфраструктуры, которую нужно мониторить.

Почему не ElasticSearch?

Будет ли поиск по данным основной функцией вашего продукта?

Если да, то ElasticSearch даст вам серьёзные преимущества. Вам придётся подавать данные в неё через ETL и управлять всем процессом, но ElasticSearch изначально предназначена для поиска. И она хорошо с ним справляется.

Если же нет, то вполне подойдёт  Postgres. Для большинства приложений более чем достаточно будет добавить немного ilike и встроенного полнотекстового поиска. При необходимости вы в дальнейшем всегда сможете добавить отдельную функцию поиска.

Почему не MSSQL или Oracle DB?

Вы должны задать себе откровенный вопрос: стоят ли они своей цены?

Я имею в виду не только саму стоимость лицензии, но и затраты на привязку к поставщику. Как только ваши данные попадут в Oracle DB, вы будете платить Oracle вечно. Вам вечно придётся обучать своих кодеров её особенностям. И вечно выбирать между enterprise-фичами и своим кошельком.

Я знаю, очень маловероятно, что вы выпустите патч для Postgres, так что не буду притворяться, что возникнет какое-то волшебство «мощи open source», но считаю, что для выбора проприетарной базы данных у вас должны быть очень конкретные потребности. Если вам не нужна какая-то совершенно уникальная фича MSSQL, без которой вы просто не можете жить, то не используйте её.

Почему не MySQL?

По этому пункту мне нужна помощь читателей.

MySQL владеет Oracle. У неё есть фичи, доступные только в enterprise-версиях. То есть в определённой степени у вас возникнут те же проблемы привязки к поставщику, как и в случае с другими базами данных.

Однако бесплатная версия MySQL уже применяется в чрезвычайно широком спектре областей. Она существует очень давно. Есть люди, знающие, как с ней работать.

Моя проблема заключается в том, что за свою карьеру я работал с ней всего около полугода. Я просто не знаю её так хорошо, чтобы обоснованно сравнивать с Postgres.

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

Почему не какие-нибудь векторные базы данных ИИ?

  • Большинство из них новые. Помните о рисках использования нового.

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

  • Даже если ваш бизнес — это ещё одно ИИ-жульничество, вам, вероятно, всё равно достаточно просто сделать import openai.

Почему не Google Sheets?

Вы правы. Здесь никаких минусов я найти не могу. Остановитесь на них.

Комментарии (62)


  1. monpa
    19.08.2024 17:09
    +6

    Почему не Excel?


    1. slonopotamus
      19.08.2024 17:09
      +10

      Потому что Google Sheets.


    1. redfox0
      19.08.2024 17:09

      ODBC Drivers for Excel


  1. saipr
    19.08.2024 17:09
    +7

    Первоначально PostgreSQL назывался POSTGRES, ссылаясь на свое происхождение как преемника базы данных Ingres, разработанной в Калифорнийском университете в Беркли

    В свою очередь "Ingres была создана как научно-исследовательский проект в Калифорнийском университете в Беркли в начале 1970-х годов."

    Я же познакомился с этой СУБД в середине 80-х годов. СУБД Ingres входила в состав операционной системы МОС ЕС, советского клона операционной системы Unix для ЕС ЭВМ. При чем она работала и на больших машинах и на персоналках ЕС18xx. И мы тогда тоже пропагандировали постулат одной ОС (Unix) и СУБД Ingres:

    Я присоединяюсь к словам автора:

    я никого не сбиваю с толку, предлагая пользоваться Postgres

    К ним стоит прислушаться.


  1. WaitEvent
    19.08.2024 17:09
    +14

    есть клон mysql не от оракла, называется mariadb и думаю большинство уже mariadb используют. у mysql есть киллер фича - там сильно круче ядро, сторидж енжин не один (и они легко подключаются) и главное - реализован UNDO log в стиле оракла. в результате нет vacuum и апдейты на таблицы с индексами не так бьют производительность. почитайте историю Uber, они очень подробно расписали проблему и почему они свалили на mysql. когда-то постгрес пытался UNDO log реализовать, но говорят Zheap инициатива сдохла, потому что в постгрес сторидж енжин прибит гвоздями и как у mysql не подменить.

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


    1. Tzimie
      19.08.2024 17:09
      +2

      Если брать профессиональные базы за деньги, то MSSQL вне конкуренции. А в нашей специфике конечно мне, как спецу по MSSQL одна дорога, на теплотрассу


      1. jakobz
        19.08.2024 17:09
        +3

        Мне вот недавно потребовалось сделать на mssql аналог intarray из postgres. Это когда в колонку пишется массив int-ов, и дальше можно фильтровать выражениями типа (1|3)&4&5. И мы расшибли лоб, и так ничего вменяемого и не придумали.

        Важна не эта конкретная задача, а то что в mssql если чего-то нет, то это даже сколхозить не из чего: типы данных не добавить, даже массив положить в колонку не во что, и передать в функцию нельзя. T-SQL - просто издевательство, а альтернатив нет. Что-то можно изображать на CLR, но облачные mssql в него не умеют.

        И вроде вот они данные, лежат в правильных b-tree как надо, алгоритмы понятно какие надо сделать. Но подлезть не дают.

        Обидно даже за нее - т.к. на низком уровне она хорошо сделана.


        1. Xexa
          19.08.2024 17:09
          +1

          Мне недавно понадобилось на Феррари перевезти картошку, как я делал это на Жигулях, но не получилось. Чтоб я не делал.

          Хотя и там и там ТС. И там и там передвигаться предназначено. Но объективно по разному сделано(хотя в основе мотор и колеса).

          Не понятно зачем сложности такие, но ок. В MsSQL есть пользовательские типы - реализуй любой. В MsSQL есть расширенные процедуры - создавай свою логику над данными.

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

          Зы: но администрирование постгри - это дичь. Там где MsSQL из коробки работает на 100%, постгрю настраивать/подстраивать для тех же результатов (на одной ОС/машине). Но это дело привычки и навыков.


          1. Tzimie
            19.08.2024 17:09

            Да, я вот слышал что для бэкапа нормального (не костыля в виде pgdump) надо на Постгре собирать кластер и делать холодный бэкап и на второй ноде

            При этом не забыть скопировать все файлы. Потому что симлинки могут ввести в заблуждение. И про то, что бэкап неполный, вы не узнаете до момента, когда обратитесь к таблице, которой не повезло


            1. Alexufo
              19.08.2024 17:09

              Wal-g


          1. Antohin
            19.08.2024 17:09

            Зы: но администрирование постгри - это дичь. Там где MsSQL из коробки работает на 100%, постгрю настраивать/подстраивать для тех же результатов (на одной ОС/машине). Но это дело привычки и навыков.

            Отчасти это "заслуга" академического прошлого базы, пошедшей от проекта университета Беркли, как написали выше, а отчасти от Unix way. Когда я первый раз узнал, что каждая таблица в PG это 3-5 файлов (Карл!), после оракл где все таблицы можно упаковать в 1 файл и настроить их так, чтоб фрагментация была минимальна, у меня глаза на лоб полезли. Понятно, что сейчас в SSD разница в доступе сильно нивелировалась, но раньше на хардах, это ж какой ад наверное был!

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


            1. vanxant
              19.08.2024 17:09
              +2

              А я вот наоборот, при работе с мускулом, если есть такая возможность, включаю режим innodb_file_per_table. Потому что когда у вас innodb упадёт, а она упадёт по питанию или ещё как, снести table_storage для одной таблицы с каким-нибудь журналом будет сильно быстрее и проще, чем двое суток вытаскивать данные из одного гигантского файла (я уж молчу про разделы, хотя оно и такое умеет, вообще без ФС)

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


              1. Antohin
                19.08.2024 17:09
                +1

                В постгре и оракл после падения по питанию обычно достаточно запустить базу - она сама восстановится если wal/redolog файлы целые. Но ведь если мы пишем через операционку, она ведь гарантирует что всё честно записано на диск, правда-правда (fsync, и всё такое)? :-)

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


        1. dude_sam
          19.08.2024 17:09

          Ну, в лоб бы я попробовал 2 варианта: кастомный дата тайп и свежую STRING_SPLIT. Потом, возможно, ещё "нормализовал" бы в COLUMNSTORE. Можно покопаться в сторону битовых масок.

          А у вас @jakobz какие были итерации и что получилось в итоге? Просто интересно...


        1. ImagineTables
          19.08.2024 17:09

          Что-то можно изображать на CLR, но облачные mssql в него не умеют.

          Из-за безопасности, поди? SQLCLR всем хорош. Я бы даже сказал, это киллер-фича MS SQL. Но из-за секьюрных ограничений даже в локальной инсталляции с ним слишком много геморроя.


          1. ptr128
            19.08.2024 17:09

            Я уже указывал выше, что из-за архитектуры MS SQL один процесс и множество нитей, уложить всю СУБД, CLR там легко и просто. При этом возможности python или rust в качестве процедурных языков PostgreSQL даже шире, чем у CLR.


            1. ImagineTables
              19.08.2024 17:09

              Понятно, что бесплатного ничего не бывает. Зато можно удобно из триггера через OLE Automation сгенерировать отчёт по таблице и приаттачить блобом. Я так делал. Я даже управление всем этим хозяйством обобщил в виде таблицы с правилами. Люблю таблицы.

              Не знаю, как с поддержкой чисто майрософтовских технологий типа OLE обстоят дела в питоне, но подозреваю, не так хорошо, как в дотнете. Кроме того, это просто очень комфортный способ писать процедурный код (хотя мне кажется, слово «императивный» тут подошло бы больше). Для меня — вообще самый. В первую очередь благодаря FCL.


              1. ptr128
                19.08.2024 17:09

                Не знаю, как с поддержкой чисто майрософтовских технологий типа OLE обстоят дела в питоне, но подозреваю, не так хорошо, как в дотнете.

                Точно так же, как .net через Win32 API и COM. И точно так же это не будет работать в любой операционной системе, отличной от Windows, как в ,net, так и в Python. Попытки сделать COM кросcплатформенным оказались безрезультатны, так что, если уж очень хочется аналогии с OLE/COM, сейчас лучше смотреть в сторону D-Bus, чем "откапывать стюардессу".

                это просто очень комфортный способ писать процедурный код

                Никто не запрещает использовать .net (С# или F#) в качестве процедурного языка PostgreSQL. Но, на мой взгляд, Rust в этих целях более предсказуемый из-за отсутствия GC.


          1. DBalashov
            19.08.2024 17:09
            +2

            https://github.com/Brick-Abode/pldotnet

            Теперь и в постгрес :)


      1. WaitEvent
        19.08.2024 17:09

        я бы не сказал. в техническом плане оракл с его UNDO log заметно красивей. mssql пишет версии строк от версионности в tempdb, который и так узкое место. ну и кластер RAC/Exadata. в техническом плане оракл пока красивей, но цена делает их обоих мало кому интересными вне облаков.


      1. ptr128
        19.08.2024 17:09
        +6

        PostgreSQL как раз очень сильный конкурент MS SQL. "Вы просто не умеете его готовить" (c).

        Я тоже спец по MS SQL с более чем двадцатилетним стажем. У MS SQL множество преимуществ перед PostgreSQL. Но верно и обратное. Одни только массивы и композитные типы (включая массивы композитных типов) многого стоят. CLR в MS SQL - костыль, которым легко можно уложить весь сервер. Например, только при создании кастомных агрегатов я нарывался на это несколько раз. Вызов кода на других языках через sp_execute_external_script и launchpad - медленный и не эффективный. А все по той причине, что MS SQL - один процесс с множеством нитей на все соединения, тогда как PostgreSQL выполняет fork() для каждого соединения, порождая отдельный процесс. Что и позволяет безопасно в этом процессе выполнять код на любом из множества процедурных языков. При возникновении критической ошибки упадет только форкнутый процесс и одно соединение, а не вся СУБД.

        Это даже не говоря о намного более широких возможностях расширения PostgreSQL, по сравнению с MS SQL. Я бы сказал, что между MS SQL и PostgreSQL +-паритет. Что то проще и/или эффективней делается на первом, что то на втором. Но мне ещё не встречались случаи, когда что то запрошенное заказчиком можно было реализовать на MS SQL, но нельзя на PostgreSQL. И наоборот.


        1. donRumatta
          19.08.2024 17:09
          +1

          Так ведь эта особенность c процессами под подключение жесткий такой косяк postgres, разве нет? Настолько, что сам по себе сервер мало лишь кто юзает, всегда в связке с пулером?

          До сих пор страдаем с лимитом подключений кластера, пытаясь распределить их между юзерами. В mssql с его потоками даже не задумывались о такой проблеме, про пул воркеров вообще узнал, когда полез разбираться, почему там в этом плане все тип-топ)

          P. S. А, и бэкап только кластера целиком та еще фича)


          1. ptr128
            19.08.2024 17:09

            Это не косяк, а идеология, позволяющая моментально вызывать хранимые процедуры на python, R, Rust и т.п. напрямую, а не через отдельный сервис launchpad, как в MS SQL, медленно и печально.

            При этом пулер позволяет решить проблему с большими издержками на создание процесса, вместо нити. А проблему медленного выполнения sp_execute_external_script в MS SQL можно решить, только отказавшись от него в пользу CLR. Но уже с риском уложить всю СУБД и только через разработку и тестирование.


          1. Antohin
            19.08.2024 17:09

            До сих пор страдаем с лимитом подключений кластера

            Там еще проблема в том, что они не стали заморачиваться глобальным кэшем для prepared statement, а сделали это на уровне сессии (процесса), сразу выделяя под него место на старте процесса. Мало того что это оверхэд на подготовку запроса, так еще оно и памяти немало ест когда сессий много. Возможно, если у вас так много сессий, поможет уменьшение размера этого кэша (хотя решение довольно спорное, надо смотреть по ситуации)


        1. Tzimie
          19.08.2024 17:09

          У сиквеля крах треда тоже не кладет сервер.


          1. ptr128
            19.08.2024 17:09

            Правильней, не всегда кладет сервер. Но если погуглите "An unhandled Microsoft .Net Framework exception occurred in sqlservr.exe", то найдете массу примеров.


        1. LeVoN_CCCP
          19.08.2024 17:09
          +2

          > Я бы сказал, что между MS SQL и PostgreSQL +-паритет. Что то проще и/или эффективней делается на первом, что то на втором.

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

          Тем не менее я согласен с тем кому вы отвечаете, что спецу с МССКЛ может быть тяжело переключиться на ПГ, если подходить к нему со своей привычкой. То есть проще его смотреть с нуля и опыт МС поможет в некоторых вещах. Администрирование абсолютно разное, а вот квери в более половины случаев совпадают (при изменении синтаксиса).


          1. ptr128
            19.08.2024 17:09

            спецу с МССКЛ может быть тяжело переключиться на ПГ

            Кому как. Мне, в свое время, переходить с IDMS на ADABAS, или с ADABAS на DB/2 было намного сложнее, чем потом с DB/2 на MS SQL и с MS SQL на PostgreSQL.

            В IT подобные переходы - дело обычное и к ним нужно быть готовым.

            Администрирование абсолютно разное

            В IDMS многие административные операции требовали макроассемблер или COBOL. После этого администрирование PostgreSQL меня уже никак напугать не могло. С другой стороны и в MS SQL я подавляющее большинство административных операций выполнял средствами T-SQL, а не GUI.


            1. LeVoN_CCCP
              19.08.2024 17:09
              +1

              > в MS SQL я подавляющее большинство административных операций выполнял средствами T-SQL, а не GUI.

              К этому все приходят, когда нужна гибкость :)


  1. Hivemaster
    19.08.2024 17:09
    +3

    Автор свалил всё в кучу, пробежал верхами, местами ввёл в заблуждение и не сказал про действительно важные моменты. Прежде всего, СУРБД - это системы с очень широкой областью применения, они подойдут в большинстве задач. В то время, как остальные перечисленные системы - это более узкоспециализированные инструменты, которые обычно требуются для решения специфических проблем. Кроме того, PostgreSQL требует намного меньше ресурсов, чем например MongoDB или Datomic. Кстати про Datomic, это графовая СУБД, а не реляционная.


  1. vlad4kr7
    19.08.2024 17:09

    Сравнивать и не упоминать https://jepsen.io/analyses ?


  1. selivanov_pavel
    19.08.2024 17:09
    +4

    у неё нет каких-то невероятных скрытых преимуществ

    Для MySQL существуюет galeracluster и percona xtradb cluster. Они при помощи galera replication позволяют сделать multi-master. Что позволяет получить очень простую и эффективную отказоустойчивость с нулевым временем фейловера про потере одной из баз - достаточно просто воткнуть перед кластером балансер, типа хапрокси. И никаких проблем с улетевшими не на ту базу запросами - в мульти-мастере они просто спокойно выполнятся.

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


    1. serhio_ssh
      19.08.2024 17:09

      Для Percona XtraDB используем ProxySQL в качестве балансировщика. А там уже правила + кеш и прочее.


  1. SWATOPLUS
    19.08.2024 17:09

    Я слышал, что на PostgreSQL жалуются девопсы, мол там сложнее её обслуживать чем Oracle или MsSQL. Хотелось бы конкретики, чем бесплатный PostgreSQL, хуже платных "ынтэрпрайз" решений, и если это незначительные вещи, тогда совет имеет смысл.

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


    1. Arm79
      19.08.2024 17:09
      +1

      Платные версии в первую очередь приобретают из-за технической поддержки


    1. ilja903
      19.08.2024 17:09
      +1

      Я не девопс, но немного разобрался в этой теме. Поправьте если пишу ерунду.

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

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

      В Постгресе надо коннекшены пулить, как и в Оракле. В Маридб и Мускуле это делать необязательно, те проблем с этим нет.

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

      Постгрес в моем бенче был на 40% быстрее при вставке чем Мария. Мария была на 10% быстрее в чтении. Возможно где-то это важно.

      В Марии Мускуле нет схем и прочих пермишеннов, в каком-то смысле тикетов к девопсам с запросом прав будет меньше. Им проще.

      В Постгресе есть 1 сторадж энжин. При супербольших таблицах в оракле марии и мускуле можно выключить транзакции и какие-то фичи и получить около 2.5х прибавку к производительности.

      В мускуле и марии вроде бы как лучше тулинг для репликации по сравнению с пг. Уж то что он более старый и проверенный сомнений нет.


  1. qrKot
    19.08.2024 17:09

    доступ к которой выполняется через границу сети.

    может, пограничные сети?


  1. DanilaX
    19.08.2024 17:09
    +2

    Автор может ответить почему не ClickHouse


    1. DBalashov
      19.08.2024 17:09
      +1

      Если серьезно - там специфичный SQL, в котором например не работают correlated subquery. Но с другой стороны там работает много другого всего. Всему своё применение вобщем.


    1. ptr128
      19.08.2024 17:09
      +1

      Я думаю, потому что речь была о OLTP, а не OLAP. Достаточно один раз сунуться в CH с INSERT/UPDATE по одной записи, чтобы понять, что для такого профиля нагрузки он совершенно не пригоден.

      Ну и columnstore и join плохо совместимы по определению. Из-за чего в CH приходится дублировать массу полей в таблицах, что ставит жирный крест на консистентности.


  1. 2medic
    19.08.2024 17:09

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

    Скорее не индекса, а внешних ключа.


    1. ptr128
      19.08.2024 17:09
      +1

      Внешние ключи никак не влияют на производительность выборки данных. Это вид ограничения. А вот индексы действительно позволяют избежать сканирования данных. А иногда вообще исключить обращение к страницам данных.


      1. 2medic
        19.08.2024 17:09

        Внешние ключи никак не влияют на производительность выборки данных

        Я где-то утверждал обратное?

        Смотрите внимательно: есть таблица, содержащая виды (типы) домашних питомцев. Всё верно? В оригинале:

        можно перейти от получения всех домашних питомцев человека

        Есть таблица владельцев домашних животных. В оригинале:

        перейти ... к получению всех владельцев домашнего питомца

        Таблица: Владельцы              Таблица: Домашние Животные
        +----+------------+             +----+------------+------------+
        | ID |   Имя      |             | ID |  Вид       | Владелец_ID|
        +----+------------+             +----+------------+------------+
        | 1  | Иван       |             | 1  | Кошка      |     1      |
        | 2  | Анна       |             | 2  | Собака     |     1      |
        | 3  | Ольга      |             | 3  | Хомяк      |     2      |
        | 4  | Павел      |             | 4  | Попугай    |     3      |
        +----+------------+             +----+------------+------------+
        

        Получить владельцев домашних питомцев можно создав реляцию между этими двумя таблицами. И индексы здесь не при чём.

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

        Вот и получается, что Вы не поняли о чём идёт речь, но минус влепили.


        1. ptr128
          19.08.2024 17:09

          Всё верно?

          Нет, так как фраза "к получению всех владельцев домашнего питомца" уже подразумевает, что у домашнего питомца могло быть несколько владельцев.

          Получить владельцев домашних питомцев можно создав реляцию между этими двумя таблицами.

          Между тремя. Таблицами. Вот только реляция далеко не всегда обозначает ограничение внешним ключом.

          И индексы здесь не при чём.

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

          Теперь пример. Почти из жизни.

          CREATE TABLE owners (
            Id    integer   NOT NULL,
            Valid daterange NOT NULL, -- период действия записи
            Name  varchar   NOT NULL, -- человек может сменить имя
            CONSTRAINT owners_PK_idx
              EXCLUDE USING GIST (Id WITH =, Valid WITH &&)
          );
          CREATE TABLE pets (
            Id    integer   NOT NULL,
            Valid daterange NOT NULL, -- период действия записи
            Name  varchar   NOT NULL, -- у питомца могут изменить кличку
            CONSTRAINT pets_PK_idx
              EXCLUDE USING GIST (Id WITH =, Valid WITH &&)
          );
          CREATE TABLE owners_to_pets (
            Id     integer   NOT NULL,
            Valid  daterange NOT NULL,
            own_id int       NOT NULL,
            pet_id int       NOT NULL,
            CONSTRAINT owners_to_pets_PK_idx
              EXCLUDE USING GIST (pet_id WITH =, Valid WITH &&)
            -- в конкретный период у питомца может быть только один владелец
          );

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

          Выборка всех владельцев питомца возможна по индексу owners_to_pets_PK_idx без сканирования таблицы owners_to_pets. А вот для того, чтобы наоборот, найти всех питомцов владельца на конкретный момент времени без сканирования таблицы, потребуется еще один индекс, например:

          CREATE INDEX owners_to_pets_reverse_idx ON owners_to_pets
            USING GIST (own_id, Valid) INCLUDE (pet_id);


          1. 2medic
            19.08.2024 17:09

            Нет, так как фраза "к получению всех владельцев домашнего питомца" уже подразумевает, что у домашнего питомца могло быть несколько владельцев.

            Абсолютно согласен. Просто было лениво рисовать pivot таблицу. Но рад, что Вы наконец-то внимательно прочитали текст сообщения и даже потратили время на аргументацию. Жаль, что минус не отозвали.

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

            Каким образом это утверждение соотносится с утверждением автора:

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

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

            Да ладно?

            CREATE TABLE owners_to_pets (
              Id     integer   NOT NULL,
              Valid  daterange NOT NULL,
              own_id int       NOT NULL,
              pet_id int       NOT NULL,
              CONSTRAINT owners_to_pets_PK_idx
                EXCLUDE USING GIST (pet_id WITH =, Valid WITH &&),
              -- в конкретный период у питомца может быть только один владелец
              
              -- Внешние ключи
              CONSTRAINT fk_owners
                FOREIGN KEY (own_id)
                REFERENCES owners(Id)
                ON DELETE CASCADE,
              
              CONSTRAINT fk_pets
                FOREIGN KEY (pet_id)
                REFERENCES pets(Id)
                ON DELETE CASCADE
            );

            Держите внешние ключи. Но будет и без них работать, как я и написал выше. Просто просторечно поля вида own_id и pet_id называют внешними ключами, хотя внешние ключи могут быть и не построены.

            Выборка всех владельцев питомца возможна по индексу owners_to_pets_PK_idx без сканирования таблицы owners_to_pets. А вот для того, чтобы наоборот, найти всех питомцов владельца на конкретный момент времени без сканирования таблицы, потребуется еще один индекс …

            Я откровенно не понимаю, почему Вы прицепились к сканированию таблицы?

            Поясняю, даже без единого индекса, СУБД найдёт искомые записи, уж как оно будет это делать, эффективно или нет, неважно. НАЙДЁТ!

            А вот если выкинуть поля own_id и pet_id — НЕ НАЙДЁТ!

            В оригинале не идёт речь о том, что можно получить всех владельцев домашнего питомца без использования seq scan. А о том, что их можно получить, добавив...

            Вот на мой взгляд, добавив ключевые поля. А никак не индексы.


            1. ptr128
              19.08.2024 17:09

              Жаль, что минус не отозвали.

              Как я могу отозвать то, что не ставил?

              Да ладно?

              Хотя бы сами попробовали бы такие внешние ключи создать, чтобы полюбоваться на сообщение "ERROR: there is no unique constraint matching given keys for referenced table "owners"".

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

              Поэтому нет и не может быть однозначного соответствия между записями owners и pets. Оно однозначно только для момента времени, но не для всего периода в owners_to_pets.

              Я откровенно не понимаю, почему Вы прицепились к сканированию таблицы?

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

              В оригинале не идёт речь о том, что можно получить всех владельцев домашнего питомца без использования seq scan. А о том, что их можно получить, добавив...

              Ну это лично Ваше восприятие. У меня оно противоположное. Я чуть ли не каждую неделю леплю Decline на PR именно из-за SeqScan в плане запроса. Даже по крошечной таблице из тысячи строк.


              1. 2medic
                19.08.2024 17:09
                +1

                Как я могу отозвать то, что не ставил?

                Прошу искренне извинить. Из контекста на Вас подумалось.

                Потому что это первое на что смотришь в плане запроса

                Так я ведь с этим и не спорю. Все знают, что seq scan на больших объёмах данных это нехорошо.

                Ну это лично Ваше восприятие

                Ну да. Это моё восприятие. Мне показалось, что автор имеет ввиду, что для поиска соподчинённых данных нужно всего лишь добавить ключевые поля. Даже своё восприятие аргументировал. А тут мне минусы лепят и рассказывают очевидные вещи о пользе индексирования. Я уж весь мозг изломал, что же я такого крамольного написал.

                Хотя бы сами попробовали

                О, и верно. Был не прав.


      1. dude_sam
        19.08.2024 17:09

        Внешние ключи никак не влияют на производительность выборки данных

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


        1. ptr128
          19.08.2024 17:09

          Я не понял о чем Вы. Приведите пример EXPLAIN ANALYZE для описываемого Вами случая.


  1. LorHobbit
    19.08.2024 17:09
    +3

    Не, ну то, что автор первым делом начинает сравнивать сабж с SQLite, которая вообще не столько СУБД, сколько библиотека доступа к данным с SQL-синтаксисом - для многих читателей это будет сигналом закрыть статью и не открывать её больше. Да, ниже уже упоминаются Oracle и MS SQL Server, но до этого места надо ещё дойти. Понятно, что автор хотел упростить себе задачу (преимущества PostgreSQL перед SQLite, разумеется, показать, куда легче), но эффект, боюсь, для читателей, которые что-то знают про базы данных, получился прямо противоположным. Если бы сразу начать сравнение Postgre vs Oracle - статья бы выглядела более серьёзной. :)

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

    Наконец, если кто-то затевает долгоиграющий проект с сильно более чем одним внедрением - ему стоит подумать над тем, чтобы сделать СУБД "сменной". У меня, например, есть опыт разработки проекта, где хранилище могло быть либо клиент-серверным (PostgreSQL), либо локальным (внутренняя СУБД - SQLite плюс выгрузка-загрузка в XML либо JSON, для пользователя локального варианта это выглядит просто как работа с XML-файлами), при этом по необходимости можно было легко перейти от одного варианта к другому, просто загрузив XML в PostgreSQL утилитой импорта. При этом порядка 90% SQL-запросов работали одинаково на обеих СУБД (кое-где таки пришлось сделать СУБД-специфичные ветки и то, главным образом, для оптимизации).


    1. Uint32
      19.08.2024 17:09

      Я несколько раз пытался делать кросс sql решения. Всегда получалось не очень. Может руки не от туда... Согласен с тем, что sqlite очень крута тем, что она либа. Очень клёво бы было заиметь аналогичную реализацию postgres.


      1. vanxant
        19.08.2024 17:09

        Слышал, какие-то чуваки скомпилили postgresql в javascript и запускали в браузере.


        1. ptr128
          19.08.2024 17:09

          Wasm, все же, а не js. И компиляция идет в LLVM, а уже оттуда - в wasm. В некоторых случаях, через промежуточный asm.js.


  1. ilja903
    19.08.2024 17:09
    +4

    Так, а самый главный конкурент MariaDB почему не упомянут? Там обещают и совместимость с оракловскими процедурами и какие-то другие фишки и совместимость с MySql с лучшим перформансом


    1. redfox0
      19.08.2024 17:09

      Справедливости ради в MariaDB 11.4 добавлена возможность использования пакетов (CREATE PACKAGE) вне режима совместимости с ORACLE.


  1. DmitryKuzmenko
    19.08.2024 17:09

    автор очень аккуратно не упомянул Firebird...


    1. say_TT_plz
      19.08.2024 17:09
      +2

      он же не некромант


      1. DmitryKuzmenko
        19.08.2024 17:09

        ваша шутка оч. могучая, конечно. Впрочем, если автор оригинального текста живет в США, то там - да, Firebird не имеет популярности. А вот в Бразилии, России, и ряде стран Европы - очень даже.


      1. ptr128
        19.08.2024 17:09
        +1

        Firebird активно развивается. Другое дело, что по функциональности ему до PostgreSQL очень далеко. Если поддержку JSON/XML хотя бы обещают, то, например, про секционирование таблиц в нем я вообще не слышал, так сначала надо туда параллельные планы запросов завезти. Так что они просто пока в разных весовых категориях.


        1. vanxant
          19.08.2024 17:09

          ну так и sqlite не в одном ряду с ораклом стоит... хотя и рядом в этой статье


          1. ptr128
            19.08.2024 17:09

            Это уже, скорее, претензия к статье. Я вижу смысл сравнения PostgreSQL только с универсальными SQL RDBMS того же класса. Иначе невольно приходим к сравнению теплого с мягким.


  1. AlexLeonov
    19.08.2024 17:09
    +2

    Если вы видите, что студент или выпускник использует MongoDB, то остановите его. Ему нужна помощь. Его ввели в заблуждение.

    Пожалуйста, ставьте плюсы статье и автору только за эту цитату, я вас прошу. Господи, наконец-то на хабре правда!