PostgreSQL — Блог Валерия Леонтьева https://valera.ws Место публикации личных заметок. Технологии, управление, бизнес, жизнь Sun, 02 Feb 2014 12:11:19 +0000 ru-RU hourly 1 https://wordpress.org/?v=5.6.2 https://valera.ws/wp-content/uploads/2020/02/favicon.png PostgreSQL — Блог Валерия Леонтьева https://valera.ws 32 32 Архитектура веб приложений: экстерьер (видео-лекция) https://valera.ws/2014.01.18~web-applications-architecture-exterio/ https://valera.ws/2014.01.18~web-applications-architecture-exterio/#respond Sat, 18 Jan 2014 17:34:57 +0000 http://valera.ws/?p=730 Читать далее Архитектура веб приложений: экстерьер (видео-лекция) ]]> Архитектура веб-приложений: экстерьерРассказ о популярной универсальной архитектуре стека, в котором работает веб-приложение. Само приложение может быть написано на любом интерпретируемом языке с использованием любого фреймворка фреймворков. В данном случае это не важно, так как архитектура программной инфраструктуры — технологического стека, в котором оно работает, отличается мало.

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

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

Смотрите в полноэкранном режиме.

]]>
https://valera.ws/2014.01.18~web-applications-architecture-exterio/feed/ 0
Установка Redmine на Debian с СУБД Postgres. Работа по HTTPS. https://valera.ws/2009.04.24~redmine-debian-postgres-https/ https://valera.ws/2009.04.24~redmine-debian-postgres-https/#comments Fri, 24 Apr 2009 09:20:51 +0000 http://valera.ws/?p=307 Читать далее Установка Redmine на Debian с СУБД Postgres. Работа по HTTPS. ]]> Стала задача установить хорошую современную систему управления задачами и багтрекинга. Выбор пал на Redmine. Фактически, Remine — это улучшенный Trac. Написан Redmine на Ruby. Основное отличие от Trac по функционалу — работа с несколькими разными проектами в связке. Кроме того, у Redmine намного шире функционал, и сделан он добротней.

Как обычно, для установки некоего нового программного обеспечения в Линуксе сразу идем в Гугл и ищем подходящие HOWTO. По Редмайну я нашел несколько разных HOWTO, из которых каждый понемногу мне помог (см. ссылки внизу).

Установка

Сначала ставим нужные пакеты.

# apt-get install ruby rake ruby1.8-dev rubygems libmysql-ruby librmagick-ruby ruby-pkg-tools build-essential postgresql libdbd-pg-perl libapache-dbi-perl libapache2-mod-perl2 libdigest-sha1-perl postgresql-common postgresql-contrib-8.3 libpgsql-ruby1.8 libpgsql-ruby postgresql-server-dev-8.3 libopenssl-ruby

Вроде ничего не упустил :)

Далее устанавливаем ruby gems.

# gem install rails mongrel mongrel_cluster

Добавляем путь к gems в переменную PATH. Для этого редактируем файл /etc/profile. Добавляем путь в конец  переменной (два раза в файле, перед путем двоеточие). У меня получилось так:

# head -n 8 /etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), …).if [ «`id -u`» -eq 0 ]; then
PATH=»/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/var/lib/gems/1.8/bin»
else
PATH=»/usr/local/bin:/usr/bin:/bin:/usr/games:/var/lib/gems/1.8/bin»
fi

Подготавливаем базу

Я решил использовать Postgres. С MySQL у меня была как минимум одна проблема: с кодировкой. Неправильно работали длины полей для русских текстов в UTF-8.

Из-под рута:

# su postgres

#createuser redmine —no-superuser —no-createdb —no-createrole —login —pwprompt –encrypted

#createdb —owner=redmine —encoding=utf-8 redmine

#exit

Пароль для пользователя введен redmine.

Скачиваем Redmine

На момент написания записи самый свежий стабильный релиз был 0.8.

# mkdir /var/www/rails_apps

# cd /var/www/rails_apps

# svn co http://redmine.rubyforge.org/svn/branches/0.8-stable redmine-0.8

Все команды далее выполняются из каталога  /var/www/rails_apps/redmine-0.8.

# cd /var/www/rails_apps/redmine-0.8

Конфигурируем доступ к базе

Создаем файл config/database.yml со следующим содержимым:

production:
adapter: postgresql
database: redmine
host: localhost
username: redmine
password: redmine

Конфигурируем SMTP

# cp config/email.yml.example config/email.yml

# vim config/email.yml

Внесите изменения в соответствии с настройками вашего SMTP-сервера.

Заполняем базу данных

# rake db:migrate RAILS_ENV=»production»

# rake redmine:load_default_data RAILS_ENV=»production»

Проверим, что все поставилось хорошо:

# mongrel_rails start —environment=production

Redmine должен работать по адресу http://localhost:3000. Для авторизации используйте логин и пароль admin. Не забудьте его позже своевременно изменить.

Настройка Redmine на работу через apache and mongrel_cluster по HTTPS

Создайте файл config/mongrel_cluster.yml следующего содержания:

group: www-data
log_file: log/mongrel.log
port: «9000»
cwd: /var/www/rails_apps/redmine-0.8
environment: production
user: www-data
pid_file: log/mongrel.pid
servers: 2

Проверьте, что все ОК:

# mongrel_rails cluster::start

Теперь вы должны получить доступ к Redmine на портах 9000 и 9001.

Для того, чтобы кластер поднимался после ребута, выполняем:

# mkdir /etc/mongrel_cluster

# ln -s /var/www/rails_apps/redmine-0.8/config/mongrel_cluster.yml /etc/mongrel_cluster/redmine.yml

# cp /var/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster /etc/init.d

# chmod +x /etc/init.d/mongrel_cluster

# /usr/sbin/update-rc.d -f mongrel_cluster defaults

Настраиваем apache2

# a2enmod proxy

# a2enmod proxy_http

# a2enmod proxy_balancer

# a2enmod rewrite

# a2enmod headers

Создайте файл /etc/apache2/sites-available/redmine со следующим содержимым:

NameVirtualHost *:443
<VirtualHost *:443>
ServerAdmin xxx@xxx.xx
ServerName redmine # Измените имя сервера, чтобы виртуальный хост подхватился!
DocumentRoot /var/www/rails_apps/redmine-0.8/public/
RequestHeader set X_FORWARDED_PROTO ‘https’

<Directory /var/www/rails_apps/redmine-0.8/public/>
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>

SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA;+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /var/www/conf/mobicon.crt
SSLCertificateKeyFile /var/www/conf/mobicon.key
<Location />
AuthType Basic
AuthName «Mobicon-Media»
AuthBasicProvider ldap
AuthLDAPUrl ldap://localhost/ou=people,dc=mobicon-media,dc=com?cn
Require ldap-group cn=mobicon,ou=groups,dc=mobicon-media,dc=com
SSLRequireSSL
</Location>

ProxyPass /images !
ProxyPass /stylesheets !
ProxyPass /javascripts !
ProxyPass /favicon.ico !
ProxyPass /static !
ProxyPass /holding !
ProxyPass /templates !
ProxyPass / balancer://redmine_cluster
ProxyPreserveHost On

<Proxy balancer://redmine_cluster>
BalancerMember http://127.0.0.1:9000
BalancerMember http://127.0.0.1:9001
Order allow,deny
Allow from all
</Proxy>

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ balancer://redmine2_cluster%{REQUEST_URI} [P,QSA,L]

ErrorLog /var/log/apache2/redmine.error.log
LogLevel warn
CustomLog /var/log/apache2/redmine.access.log combined
ServerSignature On
AddDefaultCharset Off
</VirtualHost>

Затем выполните:

# ln -s /etc/apache2/sites-available/redmine /etc/apache2/sites-enabled/redmine

# /etc/init.d/apache2 restart

Все настроено и готово к использованию!

Ссылки

http://blog.josefsson.org/2008/10/17/redmine-on-debian-lenny-using-lighttpd/

http://www.drinkingbird.net/blog/articles/2008/02/27/setting-up-a-redmine-site-on-ubuntu

http://www.redmine.org/wiki/redmine/RedmineInstall

http://ubuntuforums.org/showthread.php?t=674598&highlight=redmine

http://www.drinkingbird.net/blog/articles/tag/redmine

]]>
https://valera.ws/2009.04.24~redmine-debian-postgres-https/feed/ 3
Замена SQL_CALC_FOUND_ROWS или подсчет количества записей в PostgreSQL https://valera.ws/2008.07.24~calc-found-rows-in-postgresql/ https://valera.ws/2008.07.24~calc-found-rows-in-postgresql/#comments Thu, 24 Jul 2008 07:59:04 +0000 http://valera.ws/?p=83 Читать далее Замена SQL_CALC_FOUND_ROWS или подсчет количества записей в PostgreSQL ]]> На работе в новом проекте используется СУБД PostgreSQL. Так как до сих пор я работал с MySQL, сейчас приходится изучать и открывать для себя постгри. Первая проблема, которая меня заинтересовала — замена мускулевского SQL_CALC_FOUND_ROWS. Сходу готового решения найти не удалось. На форумах постоянно констатировали, что SQL_CALC_FOUND_ROWS в постгри нет. Некоторые писали, что надо юзать count(*). Но еще из MySQL мне известно, что поиск с count()-запросом работает почти в 2 раза медленнее, чем с SQL_CALC_FOUND_ROWS. Я консультировался у тех, кто пользуется PostgreSQL, день мучал google и в результате получил 4 варианта замены SQL_CALC_FOUND_ROWS в PostgreSQL, один из которых вполне приемлимый по скорости. Итак, сразу представлю те четыре варианта, о которых пойдет речь. Наш целевой запрос ищет в таблице записи, в которых встречается текст adf в поле `text`. Выбираем id 20 записей начиная от 180.000 по порядку и количество найденных всего. Вариант 1. Взят из phpPgAdmin. Я просто заглянул в код этого клиента для PostgreSQL и посмотрел как подсчет сделан у них при просмотре данных таблицы. Используется 2 запроса с подзапросами. Удобство в том, что не надо парсить и менять исходный запрос, чтобы подсчитать количество записей, найденных им.

select count(id) from (select id from testing where text like '%adf%') as sub;
select * from (select id from testing where text like '%adf%') as sub limit 20 offset 180000

Вариант 2. Самый простой вариант, который обычно юзают новички как в MySQL, так и в Postgres и других СУБД. 2 запроса.

select count(id) from testing where text like '%adf%';
select id from testing where text like '%adf%' limit 20 offset 180000

Вариант 3. © max_posedon. Это попытка эмуляции мускулевского SQL_CALC_FOUND_ROWS в Postgres по логике. Правда работает только при сортировке по id (в данном случае). Здесь подставляется id последней записи в выборке, т.е. записи под номером 180.000 + 20.

select * from testing where text like '%adf%' limit 20 offset 180000;
select count(id) from testing where text like '%adf%' and id > 132629;

Вариант 4. По советам пользователей irc.freenode.org, опять же max_posedon‘а, и этого ответа на форуме PostgreSQL, который прятался глубоко в гугле. Используется курсор.

DECLARE curs CURSOR FOR select id from testing where text like '%adf%';
MOVE FORWARD 180000 IN curs;
FETCH 20 FROM curs;
MOVE FORWARD ALL IN curs;

+ фунция PQcmdTuples() API Postgres (или $count = pg_cmdtuples($result); в PHP). Обратите внимание, что все 4 варианта запросов следует выполнять в одной транзакции, тогда они работают быстрее. 4й вариант вовсе не будет работать, если не использовать одну транзакцию: теряется курсор. Теперь о скоростях. Я провел тестирование скорости работы этих четырех вариантов. Вобщем-то тесты подтвердили ожидания. Но отмечу важный факт. Все запросы запускались на конфигурации PostgreSQL по умолчанию, которая не является оптимизированной на производительность. У меня под рукой просто не было оптимизированного сервера. Так что цифры могут немного корректироваться при запуске с «хорошим» конфигом. Однако суть не изменится. Тестовые запуски проводились в PHP по 20 повторов 2 раза на каждый вариант. Доступен php-скрипт, который запускал тесты. Кому интересно, есть полная статистика выборок в Excel™. Здесь опубликую лишь сводную таблицу:

Вар 1 Вар 2 Вар 3 Вар 4
Ср. время (мс) 647,41 648,25 450,64 370,67
Отношение к вар 4 1,75 1,75 1,22

Для сравнения время запросов без использования транзакции:

  • Вар 1: 1204 мс,
  • Вар 2: 689 мс,
  • Вар 3: 560 мс,
  • Вар 4 работает только в пределах транзакции.

Итоги. Самый быстрый вариант 4 с использованием курсора. Его скорость обусловлена тем, что «тяжелый» поисковый запрос выполняется только один раз. Далее проводятся операции с курсором. Аналогично работает и SQL_CALC_FOUND_ROWS в MySQL. На 20% от него отстает вариант 3 — попытка эмуляции SQL_CALC_FOUND_ROWS в PostgreSQL. Варианты 1 и 2 работат примерно с одинаковой скоростью и на 75% (более чем на 2/3!) уступают по скорости запросу с курсором.

]]>
https://valera.ws/2008.07.24~calc-found-rows-in-postgresql/feed/ 2
Камень в огород полнотекстового поиска в PostgreSQL https://valera.ws/2008.06.30~fts_postgresql/ https://valera.ws/2008.06.30~fts_postgresql/#comments Mon, 30 Jun 2008 08:30:34 +0000 http://valera.ws/2008.06.30~fts_postgresql/ Читать далее Камень в огород полнотекстового поиска в PostgreSQL ]]> PostgreSQLНа днях на работе решали вопрос о том, какой инструмент использовать для полнотекстового поиска информации. Рассматривалось много вариантов, среди которых был встроенный с версии 8.3 поиск в PostrgeSQL. К сожалению, одной маленькой мелочи не хватило в нем, чтобы мы могли его использовать. Очень горькая ложка дегтя в большой бочке меда.

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

Маленькая ложка дегтя заключается в том, что нет в полнотекстовом поиске в Postgres поиска по фразам. Мы прошуршали весь мануал по поиску, ну нету синтаксиса для запроса поиска по фразе. Я зашел на #postgres@irc.freenode.org. И там совета не дали. Спросил на известном форуме. Эффект ноль. Только один человек посоветовал пути обхода этого момента, но они такие геморройные, что не считаю нужным их тут описывать.

Похоже, что эту опцию они собираются внедрить только в будущих версиях поискового движка. http://www.sai.msu.su/~megera/wiki/todo «todo: …phrase search through new operator or adding word ordering in tsquery…»

В общем, нет в PostgreSQL 8.3 полнотекстового поиска по фразам.

]]>
https://valera.ws/2008.06.30~fts_postgresql/feed/ 1
Поиск в MySQL. Часть 3 «FULLTEXT IN BOOLEAN MODE» https://valera.ws/2008.04.15~fulltext-in-mysql/ https://valera.ws/2008.04.15~fulltext-in-mysql/#comments Tue, 15 Apr 2008 14:53:10 +0000 http://valera.ws/2008.04.15~fulltext-in-mysql/ Читать далее Поиск в MySQL. Часть 3 «FULLTEXT IN BOOLEAN MODE» ]]> Поиск с учетом русской морфологии

Поиск в MySQL. Часть 3 «FULLTEXT IN BOOLEAN MODE»

В первой части рассказа о поиске в MySQL рассказывается про использование полнотекстного индекса FULLTEXT. При поиске неких ключевых слов в большом массиве текста, хранящегося в БД, без использования индекса не обойтись. Однако родные возможности полнотекстового поиска в СУБД MySQL не обеспечиват функционал для поиска с учетом русской морфологии. Решение этой проблемы описывалось во второй части «Поиск с учетом русской морфологии». И вот недавно в описанном алгоритме обнаружился большой недостаток. Что это за недостаток и как с ним бороться и описано в этой статье.

Для начала хочу заметить один нюанс. Не так давно вышел релиз СУБД PostgreSQL 8.3. И одной из важнейших его особенностей стало то, что полнотекстный поиск, причем еще и с поддержкой русской морфологии, включен в ядро СУБД. Теперь не надо использовать различные плагины и примочки, чтобы пользоваться возможностями полнотекстного о поиска. А возможности эти на порядок мощнее и щире возможностей fulltext-поиска в MySQL. По-этому, если поиск информации в базе для вашего проекта является одной из центральных «фишек», стоит смотреть в сторону Postgres.

Если же у вас нет выбора СУБД, или требования к поиску невысокие, можно пользоваться и моим решением на базе MySQL. Только необходимо учесть поправки для поискового запроса, описанные ниже.

По делу. При использовании конструкции MATCH … AGAINST СУБД ищет указанные в запросе ключевые слова в индексе, если подходящий найден, или в указанном поле данных. Поиск может проходить в трех разных режимах: в натуральном (обычном) и логическом (boolean mode). Общее между этими режимами то, что в обоих случаях фраза поиска, переданная в AGAINST будет разделена на слова. И при поиске будут находиться записи, в которых встречается хотя бы одно из указанных слов.

Например, при указании фразы «трудовой договор» будут найдены все строки, в которых встречается слово «трудовой» и все строки со словом «договор». На практике такой подход оказывается неприемлемым, так как выдает слишком много лишних результатов. Особенно ярко выражается проблема, когда одно слово очень популярное и находится в огромном количестве строк. В этом случае уточняющее слово практически не имеет смысла. И релевантность тут не спасет. Популярное слово может встретиться в строке 50 раз. В этом случае строка получит релевантность значительно выше, чем строка в которой оба слова встретились по одному разу.

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

Для включения логического режима используется синтаксис: MATCH (…) AGAINST (‘…’ IN BOOLEAN MODE);

Оператор пишется в кавычках непосредственно перед ключевым словом, к которому он относится. Операторы, которые воспринимает анализатор запроса:

  • — (дефис, символизирующий «минус»). Этот оператор указывает, что данное ключевое слово не должно содержаться в поле (NOT);
  • + указывает, что слово должно обязательно содержаться в запросе (AND);
  • > и < соответственно увеличивают и уменьшают вес слова при подсчете релевантности;
  • ( и ) группируют слова для применения к ним оператора
  • ~ имеет смысл, схожий с «минусом», но оно слово не исключает, а просто уменьшает релевантность строки, в которой слово встретилось;
  • * — оператор усечения, ставится в конце слова и имеет классический смысл (например, слов*);
  • » (кавычка). В кавычки берутся фразы, по которым требуется искать целиком.

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

Чтобы обеспечить точный поиск и релевантность вывода, передадим в запрос ключевые слова в обработанном виде. Первой частью пустим в кавычках фразу, составленную из слов, которые ввел пользователь (естественно, предварительно отфильтровав спец-символы). Установим перед ней оператор повышения релевантности «>». Далее через пробел открываем скобки. В них нужно указать слова, полученные от морфологического движка. Перед скобками ставим оператор уменьшения релевантности. Слова пишутся через пробел, а перед каждым словом ставится оператор «+».

Для наглядности приведем пример. При поиске по фразе «отпуск за работу» запрос будет выглядеть так: … MATCH (…) AGAINST (‘>»отпуск за работу» <(+отпуск +работу)’ IN BOOLEAN MODE) …

Кроме этого, из-за логического режима поиска необходимо вручную указать порядок вывода (сортировку) найденных строк. Для этого добавляем в выборку еще один столбец, который определяется так выражением MATCH … AGAINST с псевдонимом. Причем оно должно быть идентично выражению в блоке WHERE. Тогда СУБД будет выполнять поиск только один раз. Ну а в конец запроса нужно дописать, что сортировка идет по полю (через псевдоним) в порядке убывания.

Итак, теперь пример полного результирующего запроса. Поиск по фразе «отпуск за работу» в таблице table в полях text и text_index, по которым был предварительно создан полнотекстный индекс:

SELECT SQL_CALC_FOUND_ROWS *,
MATCH (text,text_index) AGAINST (‘>»отпуск за работу» <(+отпуск +работа)’ IN BOOLEAN MODE) AS rel
FROM table
WHERE MATCH (text,text_index) AGAINST (‘>»отпуск за работу» <(+отпуск +работа)’ IN BOOLEAN MODE)
ORDER BY rel DESC LIMIT 0, 10

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

]]>
https://valera.ws/2008.04.15~fulltext-in-mysql/feed/ 14
Обо всем по-немногу https://valera.ws/2008.04.10~prosto/ https://valera.ws/2008.04.10~prosto/#comments Thu, 10 Apr 2008 18:33:43 +0000 http://valera.ws/2008.04.10~prosto/ Читать далее Обо всем по-немногу ]]> Эта запись будет не посвящена ничему конкретному. Просто набор интересностей, которые я повстречал за последние дни.

Итак, начнем с конца. Только что прочитал интересную запись в дневнике Лебедева, посвященную курению.

Сегодня пришел к окончательному выводу, что Java гавно. Почему? Все просто — она неюзабельна. Великий тормоз NetBeans, который к тому же обладает бесплатным набором багов в своем гуи. В теории у явы очень интересные и правильные подходы ко всему, но как выясняется на практике, они сложны, запутаны и не так интересны, как в теории. Человек, привыкший к MS Visual Studio и ms-way, будет чувствовать за явой себя неудобно. С C# картина абсолютно другая. Все хорошо, приятно и привычно. К тому же по яве очень мало помощи, что на сайтах в сети, то же и в irc. Сейчас пишу на яве курсач, договорился использовать его на работе. Сейчас уже жалею, что связался с ней. Ведь придется потом этот гавнокод сопровождать и развивать :(

MySQL хорошая СУБД. Но в ней гавняный полнотекстный поиск. Он не поддерживает русскую морфологию. Сегодня обнаружил, что мое решение не очень-то нормально работает. В результатах такого поиска очень много лишних результатов из-за того, что ищется по правилу «или», а не «и» между словами :( Пришел к выводу, подтвержденному Котеровым: «Собственно, на MойКруге PostgreSQL во многом как раз из-за того, что в нем есть отличный полнотекстовый поиск, который и не снился MySQL. (А в 8.3 он будет еще лучше.)». 8.3 уже вышла, буду ее осваивать.

Посидел неделю на Хабре. Сделал вывод, что половину тамошних обитателей невменяемы :( Портал опопсел (как в свое время и баш), там конечно попадаются хорошие и интересные, и полезные статьи, но половина — чушь, половина комментов — чушь, и минусуют все (карму, статьи, комменты) только по принципу «согласен/не согласен» и «модно/не модно». А жаль.

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

]]>
https://valera.ws/2008.04.10~prosto/feed/ 1
MySQL vs PostgreSQL https://valera.ws/2007.09.04~postgresql-vs-mysql/ https://valera.ws/2007.09.04~postgresql-vs-mysql/#comments Tue, 04 Sep 2007 14:28:41 +0000 http://valera.ws/2007.09.04~postgresql-vs-mysql/ Читать далее MySQL vs PostgreSQL ]]> MySQL vs PostgreSQLНеделю назад я инициировал обсуждение на одном сайтике на тему миграции с MySQL на PostgreSQL. В процессе обсуждения плавно сменили тему на сравнение этих двух популярных СУБД. В результате мне показалось, что почитать это обсуждение будет интересно и полезно многим программистам. В обсуждении участвовал известный программист PHP, автор двух книг по PHP, разработчик сервиса moikrug.ru Дмитрий Котеров.

Вот обсуждение, немного обработанное с вырезанными лишними постами.

from MySQL to PostgreSQL

Валерий Леонтьев, программист PHP/MySQL

Вопрос тем, кто уже прошел такой путь: на сколько сложен переход для программиста, на сколько велики отличия, сколько % запросов обычно надо переписать для сайта на MySQL. Все рассматривается в контексте программирвоания на PHP.

Илья Бутыльский, web-developer

Не сильно сложно. Взвесьте все «за» и «против». Может и не стоит переходить.

Валерий Леонтьев, программист PHP/MySQL

Уже взвесил. Скорость постгри при нагрузке в разы выше, чем у MySQL. При этом, предел отказоустойчивости тоже выше. Т.е. переводить мелкие проекты смысла нет, а вот крупные стоило бы.

Михаил Талисов, Магистрант, Java EE developer

У меня тоже возникала год назад необходимость переводить приложение с MySQL на PostgreSQL. Особых трудностей не возникло.

Но все же некоторые вещи пересмотреть пришлось: в PostgreSQL нет автоинкрементных полей (для автоматического инкремента ПК используется специальный тип SERIAL). И для хранения значения счетчика используются специальные конструкции — sequence. Для получения текущего значения счетчика используется нечто вроде:

«select currval(‘task_id_seq’)»

Вроде больше особых отличий нету, остальное — детали.

Дмитрий Кадыков, web-программист Интернет-гипермаркета 003.ru

Мне приходилось делать обратную операцию: перевести часть кода с Postgre на MySQL. Пришлось заменить TO_CHAR(date,’MM.YYYY’) на DATE_FORMAT(date, ‘%m.%Y\’), и в принципе всё.

Валерий Леонтьев, программист PHP/MySQL

Re: Дмитрий Кадыков

А по какой причине так пришлось сделать, если не секрет?

Антон Полумисков, PHP программист

А на каком MySQL проект находится сейчас? У постгри приемуществ конечно хватает, но может проще будет перейти на MySQL5, если проект конечно не под 5 работает )), он и быстрее чем предшественники и возможностей стало больше. Но и самое главное — возникнет значительно меньше проблем с переходом.

Валерий Леонтьев, программист PHP/MySQL

Re: Антон Полумисков

Понимаешь, тут дело такое: если бы не 5 версия MySQL, то я бы уже давно перешел на ту же PostgreSQL или что-то другое. Версии до 5 — это полупустые СУБД. Там кроме тормозючести еще и половины фишек нет, которые в других СУБД давно есть и являются стандартом.

Евгений Ненаглядов, Вэб-разработчик

А мне из мускула не хватает REPLACE. В постгресе сие реализуется только триггером на INSERT, а я еще не освоил программирование процедур.

Переводил довольно крупный проект. Нудно, но не критично.

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

Дмитрий Котеров, МойКруг.ру: сооснователь, рук. разработки

Скорость постгри при нагрузке в разы выше, чем у MySQL

Мой опыт показывает, что это совершенно неверное заявление. Все в точности да наоборот. Вы какой тип таблиц используете? Если MyISAM, то все понятно — они под нагрузкой плохо живут, если операции записи производятся сравнительно часто. Попробуйте InnoDB, они работают примерно так же, как таблицы в PostgreSQL (версионник с блокировкой строк). И попробуйте еще настройки MySQL потюнить — от них многое зависит.

Для крупных высоконагруженных проектов важное значение имеет репликация. В MySQL она встроенная и, главное, работает отлично — практически нет запаздывания при обновлении реплики. Для PostgreSQL есть Slony, однако у него: (а) раз в 10 бОльший «барьер на вход» (т.е. если с репликацией MySQL Вы в продакшене освоитесь, скажем, за неделю, то в Slony — за 10 недель), и (б) конструктивно значительный лаг при обновлении реплик, а значит, Вам придется строить приложение с учетом этого лага, что не так-то просто (встроенных средств в Slony для отслеживания этого лага [пока] нет).

Кроме того, если Вы рассчитываете с переходом на PostgreSQL обеспечить лучшую сохранность данных, то для обеспечения высокой производительности совместно с высокой надежностью нужно обязательно использовать аппаратный дисковый контроллер со встроенной кэш-памятью записи значительного размера и батарейкой (а такие контроллеры недешевы). Без аппаратного решения Вы «упретесь» в операцию fsync, которая, собственно, и обеспечивает сохранность данных, и которая несовместима с интенсивным обновлением данных без аппаратного решения.

Так что, если у Вас проект прекрасно работает на MySQL, возможностей MySQL ему хватает, то я бы категорически не рекомендовал переходить на PostgreSQL. PostgreSQL нужен для действительно сложных проектов, когда возможностей MySQL (даже 5-й версии) не хватает, когда приходится применять нереляционный подход, — например, для МойКруг. По крайней мере, в стратегическом (долгосрочном) плане повышения быстродействия при переходе с MySQL на PostgreSQL Вы точно не добьетесь.

Валерий Леонтьев, программист PHP/MySQL

Re: Дмитрий Котеров

Спасибо за столь подробный ответ. Мое «заявление» на самом деле основывалось не на личном опыте (как понятно из темы — я с постгри не работал), а не статьях других программистов. Последняя статья на эту тему, которую я прочитал была опубликована в журнале «Системный администратор» кажется за август (я не обратил внимания на номер). И как раз там у них по результатам опытов разница получилась в разы.

В MySQL медленнее работают сложные запросы: с джойнами и подзапросами. На этой почве у меня даже развилась некая фобия таких запросов. А если эх будет много в скрипте, да плюс нагрузка пиковая большая, то MySQL может и в ступор впасть. Один раз я такой ступор уже наблюдал. Правда там причина была в том, что проект был написан неграмотно (не мной) и не стояли индексы. Когда я открыл show processes, я там наблюдал кучу сложных висящих запросов. И загрузка ЦП деманом мускуля 99%. Так как времени на оптимизацию не было, да и двиг этот скоро уйдет в корзину, я не менял запросы, но просто сделал для них «правильные индексы», проблема частично решилась. Таких ступоров больше не было. И вот сложилось по статьям у меня впечатление, что с постгри такого не будет, а если и будет, то при много большей нагрузке. Тип таблиц в данном скрипте действительно MyISAM.

Александр Лещинский, Мизантропичный админ

Re: Дмитрий Котеров

Мой опыт показывает, что это совершенно неверное заявление.

нечасто я соглашаюсь с Дмитрием, но тут поддержу из всех стволов. Безмозглое неграмотное мудачье, не знающее матчасти, делает «абы как» своими руками, растущими из жопы, а потом удивляется «а шо, нам обещали что будет все шоколадно, а все совсем не так»? Любой инструмент, даже самый хороший, не отменяет необходимости думать… головой!!! а не тем, чем привыкли так называемые «работники» — очком.

Re: Валерий Леонтьев

Про журнальчик этот вобще цензурных слов нет… большего сборища ламерья я еще не встречал… Писать и проектировать надо аккуратно, чтобы не накрывал БП

Дмитрий Кадыков, web-программист Интернет-гипермаркета 003.ru

Re: Валерий Леонтьев

Да просто новому начальнику не понравилось, что одна часть проекта работает по Postgre, а всё остальное — под MySQL. Кстати, сразу же хотелось бы задать вопрос всем: может ли считаться оправданным совмещение двух СУБД в рамках одного проекта и в каких случаях стоит так делать?

Валерий Леонтьев, программист PHP/MySQL

Re: Дмитрий Котеров

Кстати, как я понял, Дмитрий Котеров повсеместно предпочитает использовать InnoDB. А как с fulltext-поиском? Используете ли Вы его? Или ищите по каким-то другим алгоритмам?

Валерий Леонтьев, программист PHP/MySQL

Re: Дмитрий Кадыков

Логически поразмышляв, пришел к выводу, что совмещение СУБД оправдано быть не может. Обычно, из 2х СУБД одна лучше. Тогда зачем делить, логичнее все делать на той, которая лучше в данной ситуации. Возможно, деление оправдано в крайне редких случаях, когда разные элементы проекта требуют функционал, доступный только в разных СУБД. Не знаю бывает ли такое вообще, но если и бывает, то крайне редко (может 1 сайт из 1000).

Александр Лещинский, Мизантропичный админ

Re: Валерий Леонтьев

Логически поразмышляв, пришел к выводу, что совмещение СУБД оправдано быть не может.

А практики говорят, что резоны могут быть…

Валерий Леонтьев, программист PHP/MySQL

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

Евгений Неверов, Я — человек!

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

Был у меня один проект, который я переносил с MySQL на PostgreSQL, так вот там по ходу дела пришлось сменить структуру таблиц. Чтобы импортировать данные я написал около 20 регулярных выражений, которые преобразовывали INSERT-запросы к нужному формату. Но в результате всё получилось очень хорошо.

Ответить

Виктор Куряшкин, Semantic Web specialist, Sun Microsystems

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

Просто «переписать запросы», сделать автоинкремент сиквенсом и все — это не аргумент.

Если вы не планируете усложнять логику на уровне субд — то точно переходить не стоит. Просто провозитесь и получите прибавку к производительности 5%, а то и потеряете в некоторых случаях.

Дмитрий Котеров, МойКруг.ру: сооснователь, рук. разработки

В MySQL медленнее работают сложные запросы: с джойнами и подзапросами

Не совсем так. Скорость выполнения запроса зависит во многом от того, «попадает» ли он, грубо говоря, в индексы. Если запрос «не попал» в индексы в MySQL и «не попал» в PostgreSQL, неверно говорить, что «в PostgreSQL этот запрос будет работать быстрее» — он в обоих случаях работает недопустимо долго.

Другое дело, что в PostgreSQL мощный планировщик и оптимизатор запросов (правда, он при этом и очень сложен, а также часто «ошибается», т.е. на его приструнение и изучение нужно тратить много времени). Кроме того, в PostgreSQL есть всякие там Hash Join и т.д. Так что, действительно, у написанного «от балды» сложного многотабличного запроса в PostgreSQL вероятность выполниться быстро выше, чем у того же запроса в MySQL. Но речь-то сейчас не о вероятностях, а о том, что запросы нужно строить грамотно, смотреть план их выполнения и «подгонять» друг под друга запрос, его план и индексы. А если все подогнанно, то и там, и там выполняется быстро, и на передний план выходит уже скорость апдейтов и простота репликации.

Кстати, как я понял, Дмитрий Котеров повсеместно предпочитает использовать InnoDB. А как с fulltext-поиском? Используете ли Вы его? Или ищите по каким-то другим алгоритмам?

Собственно, на MойКруге PostgreSQL во многом как раз из-за того, что в нем есть отличный полнотекстовый поиск, который и не снился MySQL. (А в 8.3 он будет еще лучше.) В InnoDB, к сожалению, полнотекстовых индексов и правда не бывает. Но я слышал, что есть масса внешних решений для индексации таблиц — в этом случае индекс строится с задержкой и по нему не так удобно искать, конечно, но — это лучше, чем ничего. Лично мне с ними работать не приходилось.

Опять же, если строить систему с нуля, и если в системе планируется много апдейтов данных, то лучше идти в сторону как раз раздельного хранения полнотекстового индекса и данных. Ну или хотя бы считать полнотекстовый индекс асинхронно (с задержкой) — как сделано здесь.

Насчет систем с двумя различными СУБД — почему бы и нет? Мы, например, используем и MySQL тоже (как раз там, где мало селектов, но много инсертов и апдейтов). Да, на администрирование дополнительной базы должно тратиться больше времени, однако тут есть два «но»:

1. Админ, работая с двумя базами сразу, здорово повышает свою квалификацию. Кроме того, появляется возможность сравнивать те или иные вещи.

2. MySQL очень неприхотлива и нетребовательна в администрировании (по моим приблизительным оценкам — там раз в 10 меньше подводных камней, чем в PostgreSQL), поэтому затраты на администрирование и MySQL тоже крайне малы.

Поучаствовать в обсуждении можно здесь: http://moikrug.ru/topics/216367527/

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

]]>
https://valera.ws/2007.09.04~postgresql-vs-mysql/feed/ 3