Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» PostgreSQL в сравнении

Автор: GSMD
Дата сообщения: 16.03.2005 08:44
Вопрос: использует ли кто и чем хороша?
Автор: pavluha
Дата сообщения: 16.03.2005 09:10
Использую уже давно. Больше 4 лет.
Чем хороша:
1. Бесплатность.
2. Поддержка тригеров, large object, встроенный язык plpgsql -очень похож на oracle-вский аналог, поддерживает ssl соединения и многое другое.
3. Многоплатформенная поддержка(в последней версии есть даже инсталятор модный под Windows).
4. Есть очень неплохие под нее компоненты для Delphi,Kylix,Builder - ZeosLib.
Что конкретно тебя интересует.
Автор: GSMD
Дата сообщения: 16.03.2005 10:19
pavluha
Планируется создание учетной системы, для нее выбирается БД. Выбор идет между Firebird и PostgreSQL. Вот...
Автор: OdesitVadim
Дата сообщения: 16.03.2005 13:06
народ говорит, что PostgreSQL достаточно громадный (не знаю, не юзал). Видел тесты в журнале ХАкер - там тестировали несколько серверов. Тести более-менее "стандартные" - вставка-выборка-удалении нескольких тысяч записей - PostgreSQL проиграл MySQL и SQLite. Автор считает, что может когда файлы базы будут в районе гига и выше, то ситуация может измениться. Правда "центр управления полётами" в PostgreSQL говорят крут.
Firebird хорош тем, что клиенту надо установить всего-то одну ДЛЛ (и файлик конфигурационный иногда). Скорость нормальная, Размеры тоже. Компонентов также.
Автор: gertoth
Дата сообщения: 02.06.2005 15:43
В Postgreslq поддержка транзакций есть, и хранимых процедур, в отличие от mysql.
Автор: Daeron
Дата сообщения: 10.02.2006 21:05
Поздновато конечно, но может кто будет просматривать.

1. PostgreSQL не громадный - это миф. Разве что файлов создает много.
2. Хороший, ЧЕСТНЫЙ, достаточно полный язык SQL. Т.е. очень близко к стандарту, и нету всяких приколов типа мутирование таблиц и прочих. И я ни разу не натыкался на то, что бы что-то было нельзя сделать исходя из "странных" соображений типа "я могу что-то сделать неправильно".
3. Мощные серверные языки ( ну не встречал я пока функций, которые нельзя было бы ЛЕГКО и КРАСИВО реализовать на SQL + pgplsql). Ну например генераторы - можно не создавать триггер для вставки нового ID и можно получить значение старого.
4. Кроссплатформенность - он есть практически под все ОС.
5. Всякие хорошие навороты - типа частичных индексов, функциональных индексов, полнотекстового поиска с морфологией и т.д. и т.п. Этого добра МНОГО и разного.
6. Наличие прямого общения с разработчиками Для меня подправили баг в ODBC, с высыланием dll на дом

Минус пожалуй один, на больших выборках из таблиц подтормаживает count(*), т.е. если записей под фильтр попадает больше 100 тысяч - это тормозит. Альтернатива - использовать статистику, но там могут быть неточности.

А так - пересев с PG на Oracle и Firebird понял, что меня пытаются зажать в непонятные для меня рамки ограничений. Например почему нельзя использовать для default имя функции или запрос к СУБД? Почему нельзя получить значение генератора ПОСЛЕ вставки в таблицу? и т.д.

Будут вопросы - могу ответить
Автор: TuMOXA123
Дата сообщения: 23.02.2006 17:36
Daeron, Объясни плиз чё такое "default имя функции или запрос к СУБД" ?

Значение генератора ты можешь получить в любое время суток

select gen_id(Gen_Accounts, 0) from RDB$Database

если вставляешь процедурой, то

create procedure accounts_ins(...)
returns new_id integer
begin
new_id = gen_id(Gen_accounts, 1);
insert into Accounts(Id, ...) values (New_Id, ...);
suspend;
end

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

1-4,6 относятся такаже к firebird

от отсутвия частичных индексов я никогда не страдал, но, возможно, хотел бы. в файербёрдовских индексах меня раздражает ограничение на длинну строки 252 символа по поводу поиска с морфологией: в файербёрде такое делают за счёт udf т.е. подключаемые модули, скомпилированные на чём угодно в dll или so
Автор: Daeron
Дата сообщения: 23.02.2006 17:54
TuMOXA123

Цитата:
Объясни плиз чё такое "default имя функции или запрос к СУБД" ?

Например
create table a (
"server_time" TIMESTAMP WITHOUT TIME ZONE DEFAULT ('now'::text)::timestamp(6) with time zone NOT NULL,
"id" SERIAL,
"id_pk" DEFAULT nextval('ma_log_id_seq')
);
И т.д.

Цитата:
Значение генератора ты можешь получить в любое время суток

select gen_id(Gen_Accounts, 0) from RDB$Database

И как оно по поводу транзакционной зависимости? Ну получил, а нафик нужно?
В ПГ есть функция curval() которая возвращает последний генератор в контексте текущей транзакции. Я имел в ввиду именно это.


Цитата:
от отсутвия частичных индексов я никогда не страдал

Я думаю, как и от много-го другого, но для

Цитата:
сурьёзную систему для большого предприятия

когда данных много, появится нехватка средств ускорения запросов.





Автор: TuMOXA123
Дата сообщения: 23.02.2006 18:03
Гы. Это ты хорошо объяснил - я нифига не понял Ладно, хрен с ним: кесарю кесарево
А! или это значения поумолчанию для новых записей ? Если да, то значениями по умолчнию могут быть только константы (имхо, если не путаю ничего). Сложная логика тока через триггеры. Не вижу здесь проблемы или неудобства. Даже наоборот: вижу здесь некоторе преимущество. Тебе не надо заботиться о валидности процедуры. Т.е. если тригеру передаются переменные, которые пользователь может менять или нет. То что будет, если новичёк в команде разработки поменяет тип возвращаемоего значения, а если количество возвращаемых параметров ?


Генераторы в firebird вне контекста транзакций. Они от транзакций не зависят. Значение действительно на момент получения.
Автор: Daeron
Дата сообщения: 23.02.2006 18:41
TuMOXA123

Цитата:
я нифига не понял

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


Цитата:
Сложная логика тока через триггеры. Не вижу здесь проблемы или неудобства. Даже наоборот: вижу здесь некоторе преимущество. Тебе не надо заботиться о валидности процедуры. Т.е. если тригеру передаются переменные, которые пользователь может менять или нет. То что будет, если новичёк в команде разработки поменяет тип возвращаемоего значения, а если количество возвращаемых параметров ?

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


Цитата:
Генераторы в firebird вне контекста транзакций. Они от транзакций не зависят. Значение действительно на момент получения.

В Постгрече тоже, но в текущей транзакции получить последнее полученное значение в этой транзакции - можно. И это удобно, получить вставленное значение ПОСЛЕ вставки, а не до.
Автор: TuMOXA123
Дата сообщения: 23.02.2006 19:12
Ну дату и так никто не мешает вставить поумолчанию через 'now'. А насчёт id через триггер - это не удобнее, это единобразнее. Современные средства разработки сгенерируют триггер и генератов автоматически, надо только соотв. птичку поставить.

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

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

Хотел попробовать pg на одном интернет проекте (cms), но ты меня напугал тормозными count(*). Кто-нибудь делал обстоятельный тест быстродействия таких моментов ? Почитать где-нибудь можно на эту тему что-нибудь ?

Автор: Daeron
Дата сообщения: 24.02.2006 11:53
TuMOXA123

Цитата:
Я подумал и так и не нашёл применение "последнему полученному в текущей транзакции занчению генератора". Если речь идёт об уникальном идентификаторе в базе только что вставленной записи, то, как я уже приводил пример с хранимой процедурой, делается всё элементарно.

Пример для Делфы. Например есть код, который вставляет запись в БД (ну например DB грид, или просто DataSet) и хочется получить не много не мало значение поля ID которое вставилось на в БД. Этого сделать нельзя. Да, я прекрастно понимаю, что это можно обойти, и в конце концов везде обходится, но когда с этим столкнулся при добавлении в проект поддержки FireBird пришлось попотеть что бы переделать логику работы приложения.


Цитата:
Хотел попробовать pg на одном интернет проекте (cms), но ты меня напугал тормозными count(*). Кто-нибудь делал обстоятельный тест быстродействия таких моментов ? Почитать где-нибудь можно на эту тему что-нибудь ?

Можно здесь
http://www.linuxshare.ru/postgresql/docs/postgresql-performance.html
, там правда неплохо все устарело, например min/max работают отлично, но все же почитать имеет смысл.
Основная проблема с count(), это проблема с его честностью. Напрмиер в FireBird операция count() не атомарная, нечестная, и за счет этого более быстрая. Я имею в виду, что если мы будем в транзакции 1 делать вставки по 100 записей (100 инсертов - коммит), то во второй на запрос count() мы можем увидеть число не кратноее 100. В PG все честно, но и тормозит сильнее. Под тормозит я имею ввиду, что если после применеия всех фильтров и т.д. количество записей превышает число порядка 10000 (для Celeron 1500, 512, SATA без излишеств и т.д.), то время выполнение операции может превысить пол-секунды. И для больших объемов рекомендуется или делать доп таблицу и ее апдейдить триггерами на вставку/удаление, или пользовать статистику, почаще ее обновляя (что впрочем и так рекомендуется).
Автор: gpi
Дата сообщения: 24.02.2006 14:07
Daeron

Цитата:
Пример для Делфы. Например есть код, который вставляет запись в БД (ну например DB грид, или просто DataSet) и хочется получить не много не мало значение поля ID которое вставилось на в БД. Этого сделать нельзя. Да, я прекрастно понимаю, что это можно обойти, и в конце концов везде обходится, но когда с этим столкнулся при добавлении в проект поддержки FireBird пришлось попотеть что бы переделать логику работы приложения.

В FIBPlus с использованием TpFIBDataSet.AutoUpdateOptions подобных проблем нет
Автор: Daeron
Дата сообщения: 24.02.2006 14:29
gpi

Цитата:
В FIBPlus с использованием TpFIBDataSet.AutoUpdateOptions подобных проблем нет

Ну, это же не совсем нативно, и переводить проект на FIBPlus - это не всегда возможно.
Кстати, раз там этих проблемм нет - значит фича восстребована.
Автор: TuMOXA123
Дата сообщения: 24.02.2006 18:47
Ну ладно, будем считать, что одну то полезную функцию мы в pg нашли Хотя мне, как человеку никогда не использующиму dbcontrols, пользы от неё никакой.

Твой пример с count в файербёрд мне воспроизвести не удалось - работает как часы. Но. Буду пытаться.

первый запрос через ibexpert

select count(*) from test_table;

где в test_table 300000 уникальных строковых неиндексированных записей 500ms

на p4 3.2GHz, 1GB ram, 120 Gb IDE
Автор: Daeron
Дата сообщения: 24.02.2006 19:17
TuMOXA123

Цитата:
Твой пример с count в файербёрд мне воспроизвести не удалось - работает как часы. Но. Буду пытаться.

Эта инфа от разработчиков фаерберда. Сам я такое тоже не получал.


Цитата:
первый запрос через ibexpert

select count(*) from test_table;

где в test_table 300000 уникальных строковых неиндексированных записей 500ms

на p4 3.2GHz, 1GB ram, 120 Gb IDE

Ну, я вот проверил
SELECT count(*) FROM ma_data
681283

За 1,1 секунды. Индекс по полю есть но он не используется
P4 1.7 256ОЗУ, 40Gb IDE

Автор: Fktrc
Дата сообщения: 27.02.2006 13:27

Цитата:
Индекс по полю есть но он не используется

И не должен.
Автор: Daeron
Дата сообщения: 27.02.2006 13:30
Fktrc

Цитата:
И не должен.

Ну на счет того, что не должен - это не факт (конечно по * индкекса нет , имеется ввиду PK) . В принципе мог бы и использоваться. Причина неиспользования - особенности построения движка версионности, не более того.
Автор: Fktrc
Дата сообщения: 27.02.2006 15:05
Здрасте. Если делаем выборку по всем записям без упорядочений - где тут место индексу??? Он только тормозить выборку будет.
Автор: Daeron
Дата сообщения: 27.02.2006 15:10
Fktrc

Цитата:
Здрасте. Если делаем выборку по всем записям без упорядочений - где тут место индексу??? Он только тормозить выборку будет.

Да, а почему? (с) Анекдот

В том то и дело, что count() в теории НЕ ДОЛЖЕН хотеть делать seq_scan (полный скан), а довольствоваться технической информацией из индекса. Индекс-то знает/может знать сколько в нем записей.
Если будет угодно, можно сделать так select count(id_pk) FROM my_table ORDER BY id_pk
. Индекс все равно не будет использоваться.
Автор: Fktrc
Дата сообщения: 27.02.2006 15:31
Правильно. Оптимизатор умный. Записи не выводятся - и на кой тут индекс нужен?
А насчет Индекс-то знает/может знать сколько в нем записей. - это как? Индекс - это набор полей, хранящийся в упорядоченном виде для ускорения доступа по ключу.
вот так:
ключевое поле таблицы:
2
6
43
1
8
9
5
3

индекс:
1 ссылается на запись с ключом 1 (4 по счету)
2 ссылается на запись с ключом 2 (1 по счету)
3 ссылается на запись с ключом 3 (8 по счету)
5 ...
6
8
9
43

Как ты собрался по индексу определять количество записей?
Автор: Daeron
Дата сообщения: 27.02.2006 15:41
Fktrc


Цитата:
Индекс - это набор полей, хранящийся в упорядоченном виде для ускорения доступа по ключу.


Цитата:
Как ты собрался по индексу определять количество записей?

Ты разработчик СУБД или твой пример взят из учебника?

Из этого определения не следует, что индекс НЕ ЗНАЕТ сколько в нем записей. Более того, индекс имеет размер, хранится в файлах, которыесегментированы на страницы и т.д. и т.п. Индекс - это не только набор значений ключевого упорядоченый по. Более того, индекс не хранится в планарных массивах, а зачастую или в хеше (или bitmap) или в дереве (b-tree). Для взвешивания дерева там еще куева туча доп. инфы. И в этой инфе МОЖЕТ быть информация про количество записей в индексе, и соответсвенно в таблице. И так далее. Если интерестно - можно поднять более другие источники. Например у блокировщиков, где версий данных как таковых нет - это вообще элементарно.

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

PS То что привел я - это из ответов на вопрос в официальной рассылке разработчиков постгреса + обсуждение на форуме.
Автор: Fktrc
Дата сообщения: 27.02.2006 15:53
В таком случае количество записей и индекс меж собой ну никак не взаимосвязаны. Я тебе так же скажу, что таблица (без индексов) имеет нее..чески сложную структуру и там вполне может найтись место для количества записей. Дело индекса - быстрая выборка. А такая фигулька, как кол-во записей храниться может где угодно. Приплетать к этому индекс, который может дропаться/создаваться заново, смысла не вижу.
Автор: Daeron
Дата сообщения: 27.02.2006 16:16
Fktrc

Цитата:
В таком случае количество записей и индекс меж собой ну никак не взаимосвязаны. Я тебе так же скажу, что таблица (без индексов) имеет нее..чески сложную структуру и там вполне может найтись место для количества записей. Дело индекса - быстрая выборка. А такая фигулька, как кол-во записей храниться может где угодно. Приплетать к этому индекс, который может дропаться/создаваться заново, смысла не вижу.

Продолжаем разговор.

Пусть есть таблица A на 10^7 записей, тобто десять лимонов. Каждая запись "весит" пусть по 2Кб. Есть индекс по полю a, который отсеивает в 10 раза, т.е. остается 10^6. Естественно, что select count(a) FROM huge_table WHERE a=3 будет использовать индекс для фильтрации, но не будет для count(a). А мог бы. По крайней мере в теории.
Автор: Fktrc
Дата сообщения: 28.02.2006 04:58

Цитата:
Продолжаем разговор.

Забыл добавить (C)


Цитата:
Пусть есть таблица A на 10^7 записей, тобто десять лимонов. Каждая запись "весит" пусть по 2Кб. Есть индекс по полю a, который отсеивает в 10 раза, т.е. остается 10^6. Естественно, что select count(a) FROM huge_table WHERE a=3 будет использовать индекс для фильтрации, но не будет для count(a). А мог бы. По крайней мере в теории.

При чем тут вес записи?
Что значит "индекс ... , который отсеивает" Сам по себе индекс, как структура в базе, ничего не отсеивает. Что ты хотел этим сказать?
select count(a) FROM huge_table WHERE a=3 будет использовать индекс для фильтрации
Угу.

но не будет для count(a)
А тут то зачем? Count имеет дело с уже отфильтрованной выборкой. Фильтрация проводилась по индексу и это правильно. А чтобы посчитать количество записей, нужно пробежаться по всей выборке. Конечно, можно количество считать в процессе выборки, но опять таки индекс приплетать незачем. Записи выбираются по индексу - это да. А при выполнении fCount++ на каждой полученной записи, индексу места нет - он уже отработал - выдал очередную запись.

Сдается мне, мы по разному понимаем, что такое индекс. Для меня индекс - упорядоченная структура в базе, каждый элемент которой ссылается на свою запись для ускорения доступа к записи по ключу. И не более. Если для тебя это нечто другое, приведи свое определение.
Автор: Daeron
Дата сообщения: 28.02.2006 10:32
Fktrc

Цитата:
Цитата:
Продолжаем разговор.     

Забыл добавить (C)

Согласен
Цитата:


При чем тут вес записи?
Что значит "индекс ... , который отсеивает" Сам по себе индекс, как структура в базе, ничего не отсеивает. Что ты хотел этим сказать?
select count(a) FROM huge_table WHERE a=3 будет использовать индекс для фильтрации
Угу.

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


Цитата:
но не будет для count(a)
А тут то зачем? Count имеет дело с уже отфильтрованной выборкой. Фильтрация проводилась по индексу и это правильно. А чтобы посчитать количество записей, нужно пробежаться по всей выборке. Конечно, можно количество считать в процессе выборки, но опять таки индекс приплетать незачем. Записи выбираются по индексу - это да. А при выполнении fCount++ на каждой полученной записи, индексу места нет - он уже отработал - выдал очередную запись.

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


Цитата:
Сдается мне, мы по разному понимаем, что такое индекс. Для меня индекс - упорядоченная структура в базе, каждый элемент которой ссылается на свою запись для ускорения доступа к записи по ключу. И не более. Если для тебя это нечто другое, приведи свое определение.

Для меня индекс - это объект имеющий сложную структуру данных (bitmap, btree etc), включающий в себя физическую реализацию модели хранения и использования. В том числе индекс может неявно ложится на структуру исходных данных - кластерный например. Без инфраструктуры использования - определение не полное, поскольку это могут быть разные индексы, в общем-то с одинаковой ссылочной составляющей.

Индекс может использоваться - для проверки уникальности, для ускорения поиска, для ускорения сортировки, для ускорения join и т.д. Опять же для min/max. А для count() нет, хотя мог бы

Автор: Fktrc
Дата сообщения: 28.02.2006 12:28

Цитата:
Ну, не записи, а ссылки на записи получаются из индекса.

Угу, согласен, торопился


Цитата:
Индекс занимает существенно меньше места, и "легче" "поднимается" в память, соответсвенно это будет гораздо быстрее. Размер индекса может быть в десятки/сотни раз меньше размера таблицы (в байтах).

Вон оно что имелось в виду. Теперь ясно.


Цитата:
А для count() нет, хотя мог бы

Хм, тут палка с двумя окончаниями Если проверять, существует ли запись в таблице реально (вдруг индекс порушенный) то не мог бы - все равно ведь как минимум ключевое поле каждой записи (закоммиченной, ессно, если она вставлена и еще не коммичена, ей может и ролбак прилететь) пощупать для уверенности надо.
Ну а если нам параллельно на возможную порчу индекса, тогда да - пробежались по индексу и выдали количество.
Хорошо бы узнать, как реализован count() у фаерберда, с проверкой, али без. Али там все гораздо умнее и мы тут зря офтопим
Автор: Daeron
Дата сообщения: 28.02.2006 13:03
Fktrc

Цитата:
Вон оно что имелось в виду. Теперь ясно.

Это самый простой вариант, еще просто может быть техн. ифна - по типу статистики, которую можно было бы и использовать.


Цитата:
Хм, тут палка с двумя окончаниями Если проверять, существует ли запись в таблице реально (вдруг индекс порушенный) то не мог бы - все равно ведь как минимум ключевое поле каждой записи (закоммиченной, ессно, если она вставлена и еще не коммичена, ей может и ролбак прилететь) пощупать для уверенности надо.

Ну по поводу "мертвого" индекса у PG такого вроде как не бывает, они там не дохнут обычно, да и при крешах тоже. А вот с коммитами - хуже всего, учитывая версионность движка - так полная торба.


Цитата:
орошо бы узнать, как реализован count() у фаерберда, с проверкой, али без.

Где-то на другом формуе пролетал баг, который я привел с неатомарностью count() в парллельной транзакции. И эта не-атомарность из-за использования индекса, в который записи вставляются нетранзакционно. Вполне допускаю, что это бывает мягко скажем редко, но PG слишком академический, и от таких вещей они бегут как от огня. Если должно работать атомарно - значит будет. Вот они и думают сделать не совсем честный count(), когда точное значение не важно, а скорость получения - важна.


Автор: Alochka
Дата сообщения: 20.01.2007 22:15
На сайте _http://www.citforum.ru/database/postgres95/2.shtml есть такие строки

Цитата:
Запросы могут содержать выборку данных в определенное время, в определенном интервале времени. Например, результатом запроса


SELECT city, population FROM cities['epoch','now'] WHERE city='Moscow';


будет являться следующая таблица: city population
Moscow 7 360 000
Moscow 8 950 000

Я пишу запрос
select kode ['10/11/2006', '20/01/2007'] from sotr where name='Yer'
пишет
ERROR: syntax error at or near "," у символа 21

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


Автор: Tulnov
Дата сообщения: 20.04.2008 21:31
Может кто знает, подскажите можно ли в PostgreSQL 8.3.1 средствами SQL создать функцию, возвращающую произвольный набор данных (например, данные из нескольких связанных таблиц) без создания типа для этого набора?

Страницы: 12

Предыдущая тема: WinAPI


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.