Отчасти это действенный совет, отчасти — вопрос к читателям.
Совет: при создании нового приложения, требующего постоянного хранения данных, как это и бывает в случае большинства веб-приложений, по умолчанию следует выбирать 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 с id
, name
и 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?
Вы правы. Здесь никаких минусов я найти не могу. Остановитесь на них.
Комментарии (81)
saipr
19.08.2024 17:09+9Первоначально PostgreSQL назывался POSTGRES, ссылаясь на свое происхождение как преемника базы данных Ingres, разработанной в Калифорнийском университете в Беркли
В свою очередь "Ingres была создана как научно-исследовательский проект в Калифорнийском университете в Беркли в начале 1970-х годов."
Я же познакомился с этой СУБД в середине 80-х годов. СУБД Ingres входила в состав операционной системы МОС ЕС, советского клона операционной системы Unix для ЕС ЭВМ. При чем она работала и на больших машинах и на персоналках ЕС18xx. И мы тогда тоже пропагандировали постулат одной ОС (Unix) и СУБД Ingres:
Я присоединяюсь к словам автора:
я никого не сбиваю с толку, предлагая пользоваться
Postgres
К ним стоит прислушаться.
WaitEvent
19.08.2024 17:09+18есть клон mysql не от оракла, называется mariadb и думаю большинство уже mariadb используют. у mysql есть киллер фича - там сильно круче ядро, сторидж енжин не один (и они легко подключаются) и главное - реализован UNDO log в стиле оракла. в результате нет vacuum и апдейты на таблицы с индексами не так бьют производительность. почитайте историю Uber, они очень подробно расписали проблему и почему они свалили на mysql. когда-то постгрес пытался UNDO log реализовать, но говорят Zheap инициатива сдохла, потому что в постгрес сторидж енжин прибит гвоздями и как у mysql не подменить.
но с другой стороны у mysql как-то криво реализовано чтение, похоже у них нет понятия латча и при апдейте всего одной строки на таблицу без индекса, он врубает full scan который блокирует нафиг всю таблицу. плюс у mysql сильно хуже оптимизатор.
Tzimie
19.08.2024 17:09+1Если брать профессиональные базы за деньги, то MSSQL вне конкуренции. А в нашей специфике конечно мне, как спецу по MSSQL одна дорога, на теплотрассу
jakobz
19.08.2024 17:09+3Мне вот недавно потребовалось сделать на mssql аналог intarray из postgres. Это когда в колонку пишется массив int-ов, и дальше можно фильтровать выражениями типа (1|3)&4&5. И мы расшибли лоб, и так ничего вменяемого и не придумали.
Важна не эта конкретная задача, а то что в mssql если чего-то нет, то это даже сколхозить не из чего: типы данных не добавить, даже массив положить в колонку не во что, и передать в функцию нельзя. T-SQL - просто издевательство, а альтернатив нет. Что-то можно изображать на CLR, но облачные mssql в него не умеют.
И вроде вот они данные, лежат в правильных b-tree как надо, алгоритмы понятно какие надо сделать. Но подлезть не дают.
Обидно даже за нее - т.к. на низком уровне она хорошо сделана.
Xexa
19.08.2024 17:09Мне недавно понадобилось на Феррари перевезти картошку, как я делал это на Жигулях, но не получилось. Чтоб я не делал.
Хотя и там и там ТС. И там и там передвигаться предназначено. Но объективно по разному сделано(хотя в основе мотор и колеса).
Не понятно зачем сложности такие, но ок. В MsSQL есть пользовательские типы - реализуй любой. В MsSQL есть расширенные процедуры - создавай свою логику над данными.
Ну по сути как и в постгре. Никто не обещал хранить и обрабатывать "любые данные" (хотя для них есть двоичные типы/поля или даже filestream). Мне вот постгря не нравится после перехода с MsSQL, там неудобно, тут избыточно, там кавычки одинарные/двойные не забывай писать, там тип неудачный. Но потихоньку вкатываюсь и где-то привыкаю к "неудобству", где-то улыбаюсь от "красивой" фичи, а где-то использую не замечая разницы концептуальной.
Зы: но администрирование постгри - это дичь. Там где MsSQL из коробки работает на 100%, постгрю настраивать/подстраивать для тех же результатов (на одной ОС/машине). Но это дело привычки и навыков.
Tzimie
19.08.2024 17:09Да, я вот слышал что для бэкапа нормального (не костыля в виде pgdump) надо на Постгре собирать кластер и делать холодный бэкап и на второй ноде
При этом не забыть скопировать все файлы. Потому что симлинки могут ввести в заблуждение. И про то, что бэкап неполный, вы не узнаете до момента, когда обратитесь к таблице, которой не повезло
Antohin
19.08.2024 17:09Зы: но администрирование постгри - это дичь. Там где MsSQL из коробки работает на 100%, постгрю настраивать/подстраивать для тех же результатов (на одной ОС/машине). Но это дело привычки и навыков.
Отчасти это "заслуга" академического прошлого базы, пошедшей от проекта университета Беркли, как написали выше, а отчасти от Unix way. Когда я первый раз узнал, что каждая таблица в PG это 3-5 файлов (Карл!), после оракл где все таблицы можно упаковать в 1 файл и настроить их так, чтоб фрагментация была минимальна, у меня глаза на лоб полезли. Понятно, что сейчас в SSD разница в доступе сильно нивелировалась, но раньше на хардах, это ж какой ад наверное был!
Примерно то же самое с настройками - база из коробки преднастроена так, чтобы запуститься на любом тапке, ни о какой производительности речь совершенно не идет, когда ставят такую цель. И да, много чего надо покрутить в конфиге, чтоб оно нормально заработало
vanxant
19.08.2024 17:09+4А я вот наоборот, при работе с мускулом, если есть такая возможность, включаю режим innodb_file_per_table. Потому что когда у вас innodb упадёт, а она упадёт по питанию или ещё как, снести table_storage для одной таблицы с каким-нибудь журналом будет сильно быстрее и проще, чем двое суток вытаскивать данные из одного гигантского файла (я уж молчу про разделы, хотя оно и такое умеет, вообще без ФС)
Обычно постгресу ставят в минус тот факт, что он работает с файлами исключительно поверх ФС, не занимается самостоятельно кэшированием и т.д. Но почему-то забывают про жирнющий плюс от этого решения.
Antohin
19.08.2024 17:09+1В постгре и оракл после падения по питанию обычно достаточно запустить базу - она сама восстановится если wal/redolog файлы целые. Но ведь если мы пишем через операционку, она ведь гарантирует что всё честно записано на диск, правда-правда (fsync, и всё такое)? :-)
С файлами обычно приходится возиться когда уж совсем всё пошло не так.
yrub
19.08.2024 17:09Когда я первый раз узнал, что каждая таблица в PG это 3-5 файлов (Карл!), после оракл где все таблицы можно упаковать в 1 файл и настроить их так, чтоб фрагментация была минимальна, у меня глаза на лоб полезли. Понятно, что сейчас в SSD разница в доступе сильно нивелировалась, но раньше на хардах, это ж какой ад наверное был!
а как одно зависит от другого? Диск это блочное устройство, он про файлы ничего не знает. Даже если у вас 1 файл на все таблицы, то скорее всего там есть выравнивание по размеру блока или даже кратно ему. Единственное на что влияет количество файлов в директории это на время операции ls ;)
Antohin
19.08.2024 17:09Как это не влияет? Допустим у нас full scan. Тогда если 1 файл и небольшое число экстентов на таблицу (косвенно зависит от свойств таблицы - сколько места добавлять когда оно кончается), то имеем последовательное чтение. А если записью в таблицу/файл ведает операционка, то получим кучу раскиданных по диску блоков. и полное чтение файла выльется в рандомный доступ к диску, что для HDD сильно медленнее.
Понятно что пример несколько утрирован, но если уж нам по каким-то причинам нужен fullscan (аналитику например делаем), то и так запрос будет не быстрым, а мы его еще дополнительно кратно замедляем.
Antohin
19.08.2024 17:09Хорошо, если с фулскан пример так себе, то допустим нам надо прочитать 1 строку. В оракле мы прочитаем 1 блок диска - 1 чтение. В постгре в каких-то случаях на придется прочитать данные из 3 файлов - 3 операции чтения.
yrub
19.08.2024 17:09А если записью в таблицу/файл ведает операционка, то получим кучу раскиданных по диску блоков
Зачем операционке раскидывать блоки одного файла по диску? По-моему наоборот, она будет всеми силами стараться класть блоки этого файла на диск оптимальным образом: близко друг к другу и упорядочено, и еще дефрагментацию будет запускать время от времени. А когда у вас 1 огромный файл, который содержит в себе все сразу - то такую дефрагментацию придется делать самой базе. Т.е. На уровне базы надо придумывать алгоритмы дефрагментации и работать с диском напрямую. Наверно можно извлечь плюсы, но и кактус надкусить тоже возможно.
Хорошо, если с фулскан пример так себе, то допустим нам надо прочитать 1 строку. В оракле мы прочитаем 1 блок диска - 1 чтение. В постгре в каких-то случаях на придется прочитать данные из 3 файлов - 3 операции чтения.
так и в оракле чтобы прочитать 1 блок с диска скорее всего придется читать еще какие-то другие блоки, чтоб понять откуда читать этот блок. В общем это уже все из разряда микробенчмарка и реальное влияние тут не спрогнозировать теоретически, потому что могут быть дополнительные побочные факторы.
Antohin
19.08.2024 17:09Как-то я себе с трудом представляю операционку, которая в заботе о монолитности файла оставляет дыры в свободных блоках HDD или тем более что-то куда-то двигает. Главная забота операционки - транзакционное поддержание целостности файловой системы.
Дефрагментация файлов на серваке СУБД? Такая себе затея. И так диски база дрючит, а тут еще дополнительная нагрузка.
На самом деле наш спор в нынешнее время сугубо академический. С приходом SSD никто кроме контроллера не знает где физически живет блок и никто кроме контроллера его не подвинет.
yrub
19.08.2024 17:09свободное место конечно не оставит, это может сделать и база ;) в принципе я думаю никто не мешает сделать схожий механизм работы с ораклом, просто в оракле один файл, а в постгресе 3 на каждую таблицу, а сам характер взаимодействия похожий. Я часто встречаю мнение, что 1 файл лучше чем 100, но в ситуации когда эти файлы большие, читаются произвольно и независимо - на мой взгляд разницы никакой в скорости нет, по этому за ваше утверждение зацепился.
ptr128
19.08.2024 17:09Как-то я себе с трудом представляю операционку, которая в заботе о монолитности файла оставляет дыры в свободных блоках HDD
Это называется delayed allocation.
или тем более что-то куда-то двигает.
А это copy-on-write.
С приходом SSD никто кроме контроллера не знает где физически живет блок и никто кроме контроллера его не подвинет.
Я даже более скажу, современные СХД с WAFL или подобными приемами сами эффективно такие проблемы решают.
Antohin
19.08.2024 17:09+1Согласен. Диалог носит скорее академический характер с целью разобрать тонкости баз/хранилищ :-)
ptr128
19.08.2024 17:09В PostgreSQL, таблица без индексов и out-of-storage полей - один файл. Out-of-storage - отдельный файл. Каждый индекс - тоже отдельный файл.
Если речь идет об одной физически первой записи таблицы без out-of-storage полей, то в и в Oracle, и в PostgreSQL это будет чтение одной страницы. Аналогично, при наличии out-of-storage полей, например, строки длинее 4000 байт (упрощенно, так как тут еще отдельная тема с TOAST, но мы ее опустим), в обоих СУБД потребуется чтение двух страниц. Ну и наконец, если запись с out-of-storage полем извлекается по первичному ключу и в индексе она оказалась уже в корневой странице индекса, то в обоих СУБД будет прочитано три страницы.
А количество файлов - это уже проблемы файловой системы. Собственно говоря, это и есть основная причина более медленной работы PostgreSQL под Windows (на NTFS), чем под Linux (на XFS или EXT4).
Что касается самостоятельного распределения страниц в едином файле, то тут у СУБД возможностей меньше, чем у файловой системы. Потому что она, в отличии от файловой системы, не имеет понятия, в каких экстентах (непрерывных участках) расположен файл. То есть, последовательно расположенные в файле страницы БД могут оказаться в разных экстентах, а файловая система не знает и не может знать, что они относятся к одной таблице. Тогда как если данные одной таблицы - отдельный файл, то файловая системе может оптимизировать их размещение, зная физическую структуру экстентов на диске. Для понимания, например, в NTFS, максимальный размер екстента всего лишь 2 МБ. То есть, на NTFS любой файл больше 2 МБ точно фрагментирован, как минимум, на два экстента и изменить это нельзя.
Antohin
19.08.2024 17:09В PostgreSQL, таблица без индексов и out-of-storage полей - один файл
А как же карта свободного пространства и карта видимости? ;-) 1 таблица всё-таки 3 файла даже если нет TOAST. Хотя карта свободного пространства есть и в оракл (в системных таблицах кажется), так что чтений будет плюс-минус одинаково.
Что касается самостоятельного распределения страниц в едином файле, то тут у СУБД возможностей меньше, чем у файловой системы. Потому что она, в отличии от файловой системы, не имеет понятия, в каких экстентах (непрерывных участках) расположен файл.
Поэтому оракл создает файл нужного размера сразу, чтоб фрагменированность была минимальной. Есть конечно autoextent, но тут уж разработчику решать включать его или добавлять дополнительные файлы к tablespace
С другой стороны ФС совершенно ничего не знает про данные - какой прирост данных будет в файле, с какой интенсивность. А база знает если это ей сказал разработчик или если включен сбор статистики. Вроде ораклоиды призывали отказаться от ерунды вида ручного задания свойств таблиц, мол база умная, сама порешает, но что-то у меня сомнения.
ptr128
19.08.2024 17:09А как же карта свободного пространства и карта видимости?
А они не нужны для вышеописанных трех сценариев выборки одной записи.
Поэтому оракл создает файл нужного размера сразу, чтоб фрагменированность была минимальной.
Я же указал выше, что фрагментированность всё равно будет. Причем сам Oracle даже не будет знать, где в файле заканчивается один экстент и начинается другой. И, тем более, ничего не знает о sunit и swidth, что весьма актуально уже для любого RAID, в том числе и на SSD.
С другой стороны ФС совершенно ничего не знает про данные - какой прирост данных будет в файле, с какой интенсивность.
СУБД тоже об этом мало знает. Обычно, только в рамках одной транзакции. Но и файловая система будет сбрасывать кеш на диск только после завершения транзакции и получения sync(), а лишь тогда аллоцировать место на диске под закешированные данные. При этом статистикой записи в каждый файл она тоже располагает, эвристически вычисляя allocsize в каждом случае.
ImagineTables
19.08.2024 17:09Что-то можно изображать на CLR, но облачные mssql в него не умеют.
Из-за безопасности, поди? SQLCLR всем хорош. Я бы даже сказал, это киллер-фича MS SQL. Но из-за секьюрных ограничений даже в локальной инсталляции с ним слишком много геморроя.
ptr128
19.08.2024 17:09Я уже указывал выше, что из-за архитектуры MS SQL один процесс и множество нитей, уложить всю СУБД, CLR там легко и просто. При этом возможности python или rust в качестве процедурных языков PostgreSQL даже шире, чем у CLR.
ImagineTables
19.08.2024 17:09Понятно, что бесплатного ничего не бывает. Зато можно удобно из триггера через OLE Automation сгенерировать отчёт по таблице и приаттачить блобом. Я так делал. Я даже управление всем этим хозяйством обобщил в виде таблицы с правилами. Люблю таблицы.
Не знаю, как с поддержкой чисто майрософтовских технологий типа OLE обстоят дела в питоне, но подозреваю, не так хорошо, как в дотнете. Кроме того, это просто очень комфортный способ писать процедурный код (хотя мне кажется, слово «императивный» тут подошло бы больше). Для меня — вообще самый. В первую очередь благодаря FCL.
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.
WaitEvent
19.08.2024 17:09я бы не сказал. в техническом плане оракл с его UNDO log заметно красивей. mssql пишет версии строк от версионности в tempdb, который и так узкое место. ну и кластер RAC/Exadata. в техническом плане оракл пока красивей, но цена делает их обоих мало кому интересными вне облаков.
ptr128
19.08.2024 17:09+6PostgreSQL как раз очень сильный конкурент 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. И наоборот.
donRumatta
19.08.2024 17:09+1Так ведь эта особенность c процессами под подключение жесткий такой косяк postgres, разве нет? Настолько, что сам по себе сервер мало лишь кто юзает, всегда в связке с пулером?
До сих пор страдаем с лимитом подключений кластера, пытаясь распределить их между юзерами. В mssql с его потоками даже не задумывались о такой проблеме, про пул воркеров вообще узнал, когда полез разбираться, почему там в этом плане все тип-топ)
P. S. А, и бэкап только кластера целиком та еще фича)
ptr128
19.08.2024 17:09Это не косяк, а идеология, позволяющая моментально вызывать хранимые процедуры на python, R, Rust и т.п. напрямую, а не через отдельный сервис launchpad, как в MS SQL, медленно и печально.
При этом пулер позволяет решить проблему с большими издержками на создание процесса, вместо нити. А проблему медленного выполнения sp_execute_external_script в MS SQL можно решить, только отказавшись от него в пользу CLR. Но уже с риском уложить всю СУБД и только через разработку и тестирование.
Antohin
19.08.2024 17:09До сих пор страдаем с лимитом подключений кластера
Там еще проблема в том, что они не стали заморачиваться глобальным кэшем для prepared statement, а сделали это на уровне сессии (процесса), сразу выделяя под него место на старте процесса. Мало того что это оверхэд на подготовку запроса, так еще оно и памяти немало ест когда сессий много. Возможно, если у вас так много сессий, поможет уменьшение размера этого кэша (хотя решение довольно спорное, надо смотреть по ситуации)
LeVoN_CCCP
19.08.2024 17:09+2> Я бы сказал, что между MS SQL и PostgreSQL +-паритет. Что то проще и/или эффективней делается на первом, что то на втором.
Я начинал писать подобный вашему ответ и решил стереть, потому что не умею всё сразу и по полочкам. Со своей колокольни сравнивал бы как винду и линукс - всё те же непримиримые стороны, всё та же суть где одно лучше для одного, другое для другого и также стандартами от первого нельзя подходить ко второму и наоборот.
Тем не менее я согласен с тем кому вы отвечаете, что спецу с МССКЛ может быть тяжело переключиться на ПГ, если подходить к нему со своей привычкой. То есть проще его смотреть с нуля и опыт МС поможет в некоторых вещах. Администрирование абсолютно разное, а вот квери в более половины случаев совпадают (при изменении синтаксиса).
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.
LeVoN_CCCP
19.08.2024 17:09+1> в MS SQL я подавляющее большинство административных операций выполнял средствами T-SQL, а не GUI.
К этому все приходят, когда нужна гибкость :)
QuickJoey
19.08.2024 17:09Да, сложно. Во времена версий PostgreSQL 9.4 я себя буквально заставил. Ни разу не пожалел.
Главным толчком послужила попытка поставить на нетбук с Atom на борту, "лёгкий" SQL Server Express. После 4-х часов установки, я понял, что даже в случае успеха, перестановка и трабл шутинг могут занять бесконечное время. И попробовал поставить PostgreSQL. Установка заняла 3 минуты. Таких стендов предполагалось сотня, выбор был очевиден.
inetstar
19.08.2024 17:09+1Оракл купил mysql, чтобы убить её развитие. Поэтому сейчас mysql хуже postgre.
Antohin
19.08.2024 17:09+1Оракл купил mysql чтобы залезть в другую лигу. Postgresql во многом копирует oracle, и, хотя вечно в роли догоняющего, является прямым конкурентом на рынке условного enterprise.
/*дальше сугубо мое субъективное мнение поскольку с mssql знаком слабо*/ Mysql же когда-то была "простой базой для сайтов", с тех пор много чего поменялось, но все равно как мне кажется она позиционируется как более простая СУБД без этих вот всяких заморочек.
Hivemaster
19.08.2024 17:09+5Автор свалил всё в кучу, пробежал верхами, местами ввёл в заблуждение и не сказал про действительно важные моменты. Прежде всего, СУРБД - это системы с очень широкой областью применения, они подойдут в большинстве задач. В то время, как остальные перечисленные системы - это более узкоспециализированные инструменты, которые обычно требуются для решения специфических проблем. Кроме того, PostgreSQL требует намного меньше ресурсов, чем например MongoDB или Datomic. Кстати про Datomic, это графовая СУБД, а не реляционная.
selivanov_pavel
19.08.2024 17:09+5у неё нет каких-то невероятных скрытых преимуществ
Для MySQL существуюет galeracluster и percona xtradb cluster. Они при помощи galera replication позволяют сделать multi-master. Что позволяет получить очень простую и эффективную отказоустойчивость с нулевым временем фейловера про потере одной из баз - достаточно просто воткнуть перед кластером балансер, типа хапрокси. И никаких проблем с улетевшими не на ту базу запросами - в мульти-мастере они просто спокойно выполнятся.
Для postgresql похожий уровень отказоустойчивости можно получить, только применяя всякие сложные сторонние решения. Для сопровождения которых, по моим ощущениям, потребуется отдельный DBA, глубоко разбирающийся в вопросе.
serhio_ssh
19.08.2024 17:09Для Percona XtraDB используем ProxySQL в качестве балансировщика. А там уже правила + кеш и прочее.
SWATOPLUS
19.08.2024 17:09Я слышал, что на PostgreSQL жалуются девопсы, мол там сложнее её обслуживать чем Oracle или MsSQL. Хотелось бы конкретики, чем бесплатный PostgreSQL, хуже платных "ынтэрпрайз" решений, и если это незначительные вещи, тогда совет имеет смысл.
Если платные решения покупают, то значит это зачем-то нужно. Но вот хотелось бы понять, это из-за моды или же есть реальный случаи когда платные версии нужны.
ilja903
19.08.2024 17:09+1Я не девопс, но немного разобрался в этой теме. Поправьте если пишу ерунду.
Автовакум в постгресе иногда вызывает проблемы схожие со сборкой мусора, это в случае множества апдейтов рядов.
Насколько я понял чтобы обновить постгрес по сути база реимпортируется, там все завязано на бинарных форматах, без даунтайма почти никак. Может уже нерелевантно. В Мариадб просто ставишь новую версию и она работает со старым журналом.
В Постгресе надо коннекшены пулить, как и в Оракле. В Маридб и Мускуле это делать необязательно, те проблем с этим нет.
В мускуле и марии индексы создаются автоматически на форейн ки. В постгресе это надо делать руками.
Постгрес в моем бенче был на 40% быстрее при вставке чем Мария. Мария была на 10% быстрее в чтении. Возможно где-то это важно.
В Марии Мускуле нет схем и прочих пермишеннов, в каком-то смысле тикетов к девопсам с запросом прав будет меньше. Им проще.
В Постгресе есть 1 сторадж энжин. При супербольших таблицах в оракле марии и мускуле можно выключить транзакции и какие-то фичи и получить около 2.5х прибавку к производительности.
В мускуле и марии вроде бы как лучше тулинг для репликации по сравнению с пг. Уж то что он более старый и проверенный сомнений нет.
DanilaX
19.08.2024 17:09+2Автор может ответить почему не ClickHouse
DBalashov
19.08.2024 17:09+1Если серьезно - там специфичный SQL, в котором например не работают correlated subquery. Но с другой стороны там работает много другого всего. Всему своё применение вобщем.
ptr128
19.08.2024 17:09+1Я думаю, потому что речь была о OLTP, а не OLAP. Достаточно один раз сунуться в CH с INSERT/UPDATE по одной записи, чтобы понять, что для такого профиля нагрузки он совершенно не пригоден.
Ну и columnstore и join плохо совместимы по определению. Из-за чего в CH приходится дублировать массу полей в таблицах, что ставит жирный крест на консистентности.
2medic
19.08.2024 17:09При работе с реляционной базой данных можно перейти от получения всех домашних питомцев человека к получению всех владельцев домашнего питомца, добавив в таблицы один-два индекса.
Скорее не индекса, а внешних ключа.
ptr128
19.08.2024 17:09+1Внешние ключи никак не влияют на производительность выборки данных. Это вид ограничения. А вот индексы действительно позволяют избежать сканирования данных. А иногда вообще исключить обращение к страницам данных.
2medic
19.08.2024 17:09Внешние ключи никак не влияют на производительность выборки данных
Я где-то утверждал обратное?
Смотрите внимательно: есть таблица, содержащая виды (типы) домашних питомцев. Всё верно? В оригинале:
можно перейти от получения всех домашних питомцев человека
Есть таблица владельцев домашних животных. В оригинале:
перейти ... к получению всех владельцев домашнего питомца
Таблица: Владельцы Таблица: Домашние Животные +----+------------+ +----+------------+------------+ | ID | Имя | | ID | Вид | Владелец_ID| +----+------------+ +----+------------+------------+ | 1 | Иван | | 1 | Кошка | 1 | | 2 | Анна | | 2 | Собака | 1 | | 3 | Ольга | | 3 | Хомяк | 2 | | 4 | Павел | | 4 | Попугай | 3 | +----+------------+ +----+------------+------------+
Получить владельцев домашних питомцев можно создав реляцию между этими двумя таблицами. И индексы здесь не при чём.
Нам нужно ключевое поле, на которое можно ссылаться и индекс по нему может быть вообще не построен. И внешний ключ. Строго говоря, внешний ключ тоже не обязателен. Но для целей самодокументирования и обеспечения ссылочной целостности — крайне желателен.
Вот и получается, что Вы не поняли о чём идёт речь, но минус влепили.
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);
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. А о том, что их можно получить, добавив...
Вот на мой взгляд, добавив ключевые поля. А никак не индексы.
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 в плане запроса. Даже по крошечной таблице из тысячи строк.
2medic
19.08.2024 17:09+1Как я могу отозвать то, что не ставил?
Прошу искренне извинить. Из контекста на Вас подумалось.
Потому что это первое на что смотришь в плане запроса
Так я ведь с этим и не спорю. Все знают, что seq scan на больших объёмах данных это нехорошо.
Ну это лично Ваше восприятие
Ну да. Это моё восприятие. Мне показалось, что автор имеет ввиду, что для поиска соподчинённых данных нужно всего лишь добавить ключевые поля. Даже своё восприятие аргументировал. А тут мне минусы лепят и рассказывают очевидные вещи о пользе индексирования. Я уж весь мозг изломал, что же я такого крамольного написал.
Хотя бы сами попробовали
О, и верно. Был не прав.
dude_sam
19.08.2024 17:09Внешние ключи никак не влияют на производительность выборки данных
Ну, смотря насколько "умён" движок - он может проверить первичный ключ во внешней таблице и если там пусто по фильтру, то тупо не пойдёт в запрашиваемую таблицу.
ptr128
19.08.2024 17:09Я не понял о чем Вы. Приведите пример EXPLAIN ANALYZE для описываемого Вами случая.
LorHobbit
19.08.2024 17:09+4Не, ну то, что автор первым делом начинает сравнивать сабж с SQLite, которая вообще не столько СУБД, сколько библиотека доступа к данным с SQL-синтаксисом - для многих читателей это будет сигналом закрыть статью и не открывать её больше. Да, ниже уже упоминаются Oracle и MS SQL Server, но до этого места надо ещё дойти. Понятно, что автор хотел упростить себе задачу (преимущества PostgreSQL перед SQLite, разумеется, показать, куда легче), но эффект, боюсь, для читателей, которые что-то знают про базы данных, получился прямо противоположным. Если бы сразу начать сравнение Postgre vs Oracle - статья бы выглядела более серьёзной. :)
Упоминание NoSQL-решений... Вообще, это крайне холиварная тема, но правильнее всего было бы упомянуть, что реляционные и нереляционные СУБД можно не противопоставлять, а сочетать. И в некоторых крупных проектах так и делают (если не ошибаюсь, про авито был такой доклад, и кажется, там PostgreSQL и упоминался, но это неточно). А так да, если человек не собирается делать миллионы транзакций в минуту и сразу тащит в рот NoSQL исключительно из соображений того, что он сэкономит время на проектировании структуры данных - он делает неправильно, тут соглашусь с автором.
Наконец, если кто-то затевает долгоиграющий проект с сильно более чем одним внедрением - ему стоит подумать над тем, чтобы сделать СУБД "сменной". У меня, например, есть опыт разработки проекта, где хранилище могло быть либо клиент-серверным (PostgreSQL), либо локальным (внутренняя СУБД - SQLite плюс выгрузка-загрузка в XML либо JSON, для пользователя локального варианта это выглядит просто как работа с XML-файлами), при этом по необходимости можно было легко перейти от одного варианта к другому, просто загрузив XML в PostgreSQL утилитой импорта. При этом порядка 90% SQL-запросов работали одинаково на обеих СУБД (кое-где таки пришлось сделать СУБД-специфичные ветки и то, главным образом, для оптимизации).
Uint32
19.08.2024 17:09Я несколько раз пытался делать кросс sql решения. Всегда получалось не очень. Может руки не от туда... Согласен с тем, что sqlite очень крута тем, что она либа. Очень клёво бы было заиметь аналогичную реализацию postgres.
ilja903
19.08.2024 17:09+4Так, а самый главный конкурент MariaDB почему не упомянут? Там обещают и совместимость с оракловскими процедурами и какие-то другие фишки и совместимость с MySql с лучшим перформансом
redfox0
19.08.2024 17:09Справедливости ради в MariaDB 11.4 добавлена возможность использования пакетов (CREATE PACKAGE) вне режима совместимости с ORACLE.
DmitryKuzmenko
19.08.2024 17:09+1автор очень аккуратно не упомянул Firebird...
say_TT_plz
19.08.2024 17:09+2он же не некромант
DmitryKuzmenko
19.08.2024 17:09+2ваша шутка оч. могучая, конечно. Впрочем, если автор оригинального текста живет в США, то там - да, Firebird не имеет популярности. А вот в Бразилии, России, и ряде стран Европы - очень даже.
ptr128
19.08.2024 17:09+2Firebird активно развивается. Другое дело, что по функциональности ему до PostgreSQL очень далеко. Если поддержку JSON/XML хотя бы обещают, то, например, про секционирование таблиц в нем я вообще не слышал, так сначала надо туда параллельные планы запросов завезти. Так что они просто пока в разных весовых категориях.
AlexLeonov
19.08.2024 17:09+8Если вы видите, что студент или выпускник использует MongoDB, то остановите его. Ему нужна помощь. Его ввели в заблуждение.
Пожалуйста, ставьте плюсы статье и автору только за эту цитату, я вас прошу. Господи, наконец-то на хабре правда!
Kingas
19.08.2024 17:09+1Ещё преимущество MSSQL, например, что T-SQL умеет бекапить в 1 файл и не было такого, что бэкап не полный или не работал. И он легко бэкапит на ходу. Но его подымет только текущая или любая последующая версия MSSQL. По мне хороший компромисс за предсказуемость и стабильность бекапов, про сравнению с PostgreSQL.
vladimir_2
19.08.2024 17:09Полезная статья.
Действительно postgres сейчас развивается очень быстро и наверное совсем скоро навяжет конкуренцию oracle db.
monpa
Почему не Excel?
slonopotamus
Потому что Google Sheets.
redfox0
ODBC Drivers for Excel