<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-193160215117996166</id><updated>2026-02-22T15:10:39.059+03:00</updated><category term="russian"/><category term="postgresql"/><category term="translation"/><category term="q and a"/><category term="Sergey Konoplev"/><category term="Hubert Lubaczewski"/><category term="pg84"/><category term="pg90"/><category term="configuration"/><category term="pg85"/><category term="index"/><category term="sql"/><category term="english"/><category term="blogging"/><category term="emacs"/><category term="performance"/><category term="pg91"/><category term="pgsql-general"/><category term="function"/><category term="notice"/><category term="psql"/><category term="vacuum"/><category term="xmonad"/><category term="Bruce Momjian"/><category term="logs"/><category term="statistics"/><category term="administration"/><category term="aggregate"/><category term="autovacuum"/><category term="conky"/><category term="dzen"/><category term="fun"/><category term="krasnodar"/><category term="pg_stat_activity"/><category term="plpgsql"/><category term="system tables"/><category term="transaction"/><category term="David Fetter"/><category term="Leo Hsu"/><category term="Pavel Stehule"/><category term="Regina Obe"/><category term="array_agg"/><category term="backup"/><category term="bitmap index scan"/><category term="btree_gist"/><category term="buffers"/><category term="bug"/><category term="consulting"/><category term="contrib"/><category term="count"/><category term="cube"/><category term="explain"/><category term="foreign key"/><category term="locale"/><category term="locks"/><category term="nosql"/><category term="null"/><category term="order"/><category term="order by"/><category term="over partition"/><category term="primary key"/><category term="release"/><category term="replication"/><category term="sql-mode"/><category term="sql-standart"/><category term="tag cloud"/><category term="tander"/><category term="trigger"/><category term="unnest"/><category term="window functions"/><category term="windows"/><category term="work"/><category term="Andreas Scherbaum"/><category term="Bernd Helmle"/><category term="GSoC"/><category term="Joshua Drake"/><category term="Tom Lane"/><category term="Vhubuo"/><category term="acpi"/><category term="alter table"/><category term="analysis"/><category term="arrays"/><category term="battery"/><category term="bitmap heap scan"/><category term="cassandra"/><category term="cluster"/><category term="collation"/><category term="column"/><category term="concat"/><category term="concat_ws"/><category term="conditional"/><category term="conninfo"/><category term="cpu"/><category term="create table"/><category term="ctype"/><category term="cursor"/><category term="data types"/><category term="ddl"/><category term="desktop"/><category term="dialog"/><category term="digest"/><category term="dired"/><category term="enum"/><category term="exception"/><category term="files"/><category term="floating"/><category term="frames"/><category term="fsm"/><category term="generate_series"/><category term="graph"/><category term="group by"/><category term="hot standby"/><category term="idle"/><category term="if not exists"/><category term="in"/><category term="information_schema"/><category term="junction"/><category term="left"/><category term="limit"/><category term="linux"/><category term="lock"/><category term="londiste"/><category term="loosy index"/><category term="maintenance"/><category term="mongodb"/><category term="monitoring"/><category term="moscow"/><category term="mysql"/><category term="news"/><category term="not in"/><category term="offset"/><category term="oid"/><category term="pagination"/><category term="pg_buffercache"/><category term="pg_dump"/><category term="pg_indexes_size"/><category term="pg_locks"/><category term="pg_migrator"/><category term="pg_relation_size"/><category term="pg_restore"/><category term="pg_stat_statements"/><category term="pg_table_size"/><category term="pg_total_relation_size"/><category term="pg_xlog"/><category term="pgfouine"/><category term="pgq"/><category term="pitr"/><category term="plproxy"/><category term="port"/><category term="postgresmen"/><category term="process"/><category term="profession"/><category term="ps"/><category term="python"/><category term="recheck cond"/><category term="reindex"/><category term="returning"/><category term="reverse"/><category term="right"/><category term="rule"/><category term="schema"/><category term="scripting"/><category term="seq scan"/><category term="sharding"/><category term="shell"/><category term="size"/><category term="skytools"/><category term="sniplet"/><category term="social network"/><category term="sql.ru"/><category term="srf"/><category term="ssh"/><category term="standby"/><category term="stats"/><category term="streaming"/><category term="string_agg"/><category term="strings"/><category term="temp tables"/><category term="thoughts"/><category term="transposition"/><category term="values"/><category term="view"/><category term="visibility maps"/><category term="wal"/><category term="with"/><category term="with recursive"/><category term="xxkb"/><title type='text'>gray-hemp: PostgreSQL, Emacs, Linux, etc.</title><subtitle type='html'>one flew east one flew west one flew over the cuckoo&#39;s nest</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>102</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-1941517074583755875</id><published>2010-11-01T09:03:00.005+03:00</published><updated>2010-11-01T10:49:53.033+03:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="in"/><category scheme="http://www.blogger.com/atom/ns#" term="null"/><category scheme="http://www.blogger.com/atom/ns#" term="pgsql-general"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Tom Lane"/><title type='text'>Как получить пустое множество в IN</title><content type='html'>Прочитал в рассылке &lt;a href=&quot;http://archives.postgresql.org/pgsql-general/2010-10/msg01135.php&quot;&gt;интересную дискуссию&lt;/a&gt;. Вопрос довольно злободневный, но, честно говоря, раньше не знал об этом.&lt;br /&gt;&lt;br /&gt;Допустим надо проверить, что поле входит в какое-то множество. Очевидно, что надо использовать конструкцию типа &lt;br /&gt;&lt;br /&gt;&lt;code&gt;field IN (1, 2, 3, ...)&lt;/code&gt; &lt;br /&gt;&lt;br /&gt;Но что если это множество пустое. Как его указать?&lt;br /&gt;&lt;br /&gt;&lt;code&gt;field IN (???)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Действительно, просто пустые скобки указать нельзя, получим ошибку. &lt;br /&gt;&lt;br /&gt;&lt;code&gt;postgres@localhost:5432 test=#&lt;br /&gt;SELECT 1 IN ();&lt;br /&gt;ERROR:  syntax error at or near &quot;)&quot;&lt;br /&gt;LINE 1: SELECT 1 IN ();&lt;br /&gt;                     ^&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Просто NULL тоже нельзя.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;postgres@localhost:5432 test=#&lt;br /&gt;SELECT 1 IN NULL;&lt;br /&gt;ERROR:  syntax error at or near &quot;NULL&quot;&lt;br /&gt;LINE 1: SELECT 1 IN NULL;&lt;br /&gt;                    ^&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;NULL в скобках опять нельзя, т.к. в результате всегда будет NULL.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;postgres@localhost:5432 test=#&lt;br /&gt;SELECT 1 IN (NULL);&lt;br /&gt; ?column? &lt;br /&gt;----------&lt;br /&gt; &lt;NULL&gt;&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Как тогда быть? Ответ получается из вопроса - просто &lt;b&gt;получить&lt;/b&gt; пустое множество.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;postgres@localhost:5432 test=#&lt;br /&gt;SELECT 1 IN (SELECT 1 WHERE FALSE);&lt;br /&gt; ?column? &lt;br /&gt;----------&lt;br /&gt; f&lt;br /&gt;(1 row)&lt;br /&gt;&lt;br /&gt;postgres@localhost:5432 test=#&lt;br /&gt;SELECT 1 NOT IN (SELECT 1 WHERE FALSE);&lt;br /&gt; ?column? &lt;br /&gt;----------&lt;br /&gt; t&lt;br /&gt;(1 row)&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/1941517074583755875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/11/in.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1941517074583755875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1941517074583755875'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/11/in.html' title='Как получить пустое множество в IN'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-4822725321382544840</id><published>2010-10-29T08:44:00.003+04:00</published><updated>2010-10-29T10:03:46.604+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="pgsql-general"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="schema"/><title type='text'>Как перенести объекты из одной схемы в другую</title><content type='html'>Этот вопрос довольно часто задают на форумах и в рассылке. Вот &lt;a href=&quot;http://archives.postgresql.org/pgsql-general/2010-10/msg01007.php&quot;&gt;очередное такое письмо&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Стандартное решение проблемы:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ALTER TABLE table_name SET SCHEMA new_schema;&lt;br /&gt;ALTER FUCNTION function_name SET SCHEMA new_schema;&lt;br /&gt;-- и т.д.&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/4822725321382544840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/4822725321382544840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/4822725321382544840'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/blog-post.html' title='Как перенести объекты из одной схемы в другую'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-4084908754979156058</id><published>2010-10-27T09:37:00.005+04:00</published><updated>2010-10-27T09:49:31.408+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="foreign key"/><category scheme="http://www.blogger.com/atom/ns#" term="index"/><category scheme="http://www.blogger.com/atom/ns#" term="pgsql-general"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><title type='text'>Зачем CASCADE в DROP INDEX</title><content type='html'>Читая рассылку pgsql-general, cделал для себя интересное замечание. Вопрос был - для чего указывать CASCADE в DROP INDEX, что может зависеть от индекса? Ответ - если индекс UNIQUE, то FOREIGN KEY.&lt;br /&gt;&lt;br /&gt;Источник &lt;a href=&quot;http://archives.postgresql.org/pgsql-general/2010-10/msg00931.php&quot;&gt;тут&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/4084908754979156058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/cascade-drop-index.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/4084908754979156058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/4084908754979156058'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/cascade-drop-index.html' title='Зачем CASCADE в DROP INDEX'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-1973223758825745498</id><published>2010-10-27T09:19:00.003+04:00</published><updated>2010-10-27T09:49:43.628+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="plpgsql"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><category scheme="http://www.blogger.com/atom/ns#" term="trigger"/><title type='text'>Заметка про RENAME и триггера</title><content type='html'>В plpgsql триггерах удобно использовать &lt;a href=&quot;http://www.postgresql.org/docs/8.4/interactive/plpgsql-declarations.html#PLPGSQL-DECLARATION-RENAMING-VARS&quot;&gt;RENAME&lt;/a&gt; для того чтобы абстрагироваться от NEW и OLD. Например:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;IF TG_OP = &#39;DELETE&#39; THEN&lt;br /&gt;    RENAME OLD TO myrow;&lt;br /&gt;ELSE&lt;br /&gt;    RENAME NEW TO myrow;    &lt;br /&gt;END IF;&lt;br /&gt;&lt;br /&gt;-- Далее работаем с myrow не задумываясь о типе триггера&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/1973223758825745498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/rename.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1973223758825745498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1973223758825745498'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/rename.html' title='Заметка про RENAME и триггера'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-9174739207993083247</id><published>2010-10-27T08:54:00.006+04:00</published><updated>2010-10-27T09:49:43.631+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="foreign key"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="primary key"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="sql.ru"/><category scheme="http://www.blogger.com/atom/ns#" term="system tables"/><title type='text'>Какие колонки таблицы входят в PK/FK</title><content type='html'>Вчера на sql.ru увидел вопрос - &lt;a href=&quot;http://www.sql.ru/forum/actualthread.aspx?bid=7&amp;tid=801186&quot;&gt;возможно ли при помощи запроса узнать какая колонка в таблице является PK а какая FK&lt;/a&gt;. Небольшое замечание к формулировке - в обоих случаях может быть несколько столбцов. &lt;br /&gt;&lt;br /&gt;Собственно запрос получается такой:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT &lt;br /&gt;    contype, -- тип ограничения (PK/FK)&lt;br /&gt;    attname -- имя атрибута&lt;br /&gt;FROM pg_constraint&lt;br /&gt;JOIN pg_attribute ON&lt;br /&gt;    attrelid = conrelid AND&lt;br /&gt;    attnum = any(conkey)&lt;br /&gt;WHERE&lt;br /&gt;    contype in (&#39;p&#39;, &#39;f&#39;) AND&lt;br /&gt;    conrelid = &#39;yourtablename&#39;::regclass::oid&lt;br /&gt;ORDER BY 1, attnum;&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/9174739207993083247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/pkfk.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/9174739207993083247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/9174739207993083247'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/10/pkfk.html' title='Какие колонки таблицы входят в PK/FK'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-3933371677436126387</id><published>2010-09-20T16:08:00.004+04:00</published><updated>2010-09-20T17:09:39.280+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="pg90"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="release"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>Доступен PostgreSQL 9.0 Final Release!</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.postgresql.org/about/news.1235&quot;&gt;PostgreSQL 9.0 Final Release Available Now!&lt;/a&gt; с &lt;a href=&quot;http://www.postgresql.org&quot;&gt;PostgreSQL&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Опубликовано &lt;b&gt;2010-09-20, press@postgresql.org&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Вышел PostgreSQL 9.0! The PostgreSQL Global Development Group анонсирует выход долгожданного релиза. PostgreSQL 9.0 включает встроенную бинарную репликацию и более дюжины других больших нововведений расчитанных на всех от web разработчиков до хакеров БД.&lt;br /&gt;&lt;br /&gt;9.0 реализует большее количество крупных возможностей, чем любой релиз до этого, включая:&lt;br /&gt;&lt;br /&gt;- Hot standby&lt;br /&gt;- Потоковую репликацию&lt;br /&gt;- In-place обновления&lt;br /&gt;- 64-bit Windows сборки&lt;br /&gt;- Облегченное массовое управления правами&lt;br /&gt;- Анонимные блоки и именованные параметры для хранимых процедур&lt;br /&gt;- Новые windowing функции и упорядоченные агрегаты&lt;br /&gt;&lt;br /&gt;... и многое другое. Более детальное описание свыше 200 дополнений и улучшений в этой версии, разработанные более чем сотней людей, вы сможете найти в &lt;a href=&quot;http://www.postgresql.org/docs/9.0/static/release-9-0&quot;&gt;замечаниях к релизу&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&quot;Такие нововведения являются прочным основанием тому, что критически важные технические задачи могут продолжать опираться на мощь, гибкость и надёжность PostgreSQL&quot;, Afilias CTO Ram Mohan&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Больше информации о PostgreSQL 9.0:&lt;br /&gt;- &lt;a href=&quot;http://www.postgresql.org/docs/9.0/static/release-9-0&quot;&gt;Замечания к релизу&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;http://www.postgresql.org/about/press/presskit90&quot;&gt;Пресс-кит&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;http://wiki.postgresql.org/wiki/What&#39;s_new_in_PostgreSQL_9.0&quot;&gt;Руководство по 9.0&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;Скачать 9.0 сейчас:&lt;br /&gt;- &lt;a href=&quot;http://www.postgresql.org/download&quot;&gt;Главная страница загрузки&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;http://www.postgresql.org/ftp/source/v9.0.0&quot;&gt;Исходный код&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;http://www.postgresql.org/ftp/binary/v9.0.0&quot;&gt;Бинарные пакеты&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;http://www.enterprisedb.com/products/pgdownload.do&quot;&gt;Установка в один клик, включая пакеты для Windows&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/3933371677436126387/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/09/postgresql-90-final-release.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/3933371677436126387'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/3933371677436126387'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/09/postgresql-90-final-release.html' title='Доступен PostgreSQL 9.0 Final Release!'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-2365815672237584130</id><published>2010-09-07T18:45:00.007+04:00</published><updated>2010-09-10T19:00:51.070+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="port"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><category scheme="http://www.blogger.com/atom/ns#" term="ssh"/><title type='text'>Локально работаем с PostgreSQL закрытом на сервере</title><content type='html'>Уже не в первый раз мне задают такой вопрос.&lt;br /&gt;&lt;br /&gt;Как подключиться, например с помощью pgAdmin, к кластеру PostgreSQL, когда он где-то на сервере, где его порт доступен только локально, т.е. к нему закрыт доступ извне? При этом есть ssh на этот сервер, но по нему работать в консоли с psql и тестировать работающее с базой приложение очень не удобно.&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Всё очень просто - нам поможет старый добрый ssh-туннелинг. Допустим есть сервер servername где на локальном порту 5432 крутится PostgreSQL, и есть пользователь username, который может ходить по ssh на этот сервер. Надо сделать так чтобы обращаясь к локальному порту 5432 на вашей рабочей машине вы фактически попадали на локальный порт 5432 нашего сервера.&lt;br /&gt;&lt;br /&gt;Если вы на Windows, то смотрите в сторону утилиты &lt;a href=&quot;http://www.chiark.greenend.org.uk/~sgtatham/putty/docs.html&quot;&gt;PuTTY&lt;/a&gt;, я в своё время на ней такое делал. Если вы на Linux, как и я сейчас, то вам нужна такая комманда:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ssh -L 5432:localhost:5432 username@servername&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;У меня, кстати, несколько серверов пробрасываются на разные локальные порты на рабочей машине:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;ssh -L 5432:localhost:5432 gray@server1&lt;br /&gt;ssh -L 6432:localhost:5432 gray@server2&lt;br /&gt;ssh -L 7432:localhost:5432 gray@server3&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Очень удобно.&lt;br /&gt;&lt;br /&gt;p.s. Ещё одна &lt;a href=&quot;http://linuxproblem.org/art_9.html&quot;&gt;полезная ссылка&lt;/a&gt;, где рассказывается как пользоваться ssh по сертификату, т.е. без надобности вводить каждый раз пароль.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/2365815672237584130/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/09/postgresql.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2365815672237584130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2365815672237584130'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/09/postgresql.html' title='Локально работаем с PostgreSQL закрытом на сервере'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-2991796156777725367</id><published>2010-09-07T15:48:00.004+04:00</published><updated>2010-09-07T18:42:49.322+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="concat"/><category scheme="http://www.blogger.com/atom/ns#" term="concat_ws"/><category scheme="http://www.blogger.com/atom/ns#" term="Hubert Lubaczewski"/><category scheme="http://www.blogger.com/atom/ns#" term="left"/><category scheme="http://www.blogger.com/atom/ns#" term="pg91"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="reverse"/><category scheme="http://www.blogger.com/atom/ns#" term="right"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>В ожидании 9.1 - concat, concat_ws, right, left, reverse</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.depesz.com/index.php/2010/08/24/waiting-for-9-1-concat-concat_ws-right-left-reverse/&quot;&gt;Waiting for 9.1 - concat, concat_ws, right, left, reverse&lt;/a&gt; с &lt;a href=&quot;http://www.depesz.com/&quot;&gt;select * from depesz;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;24 августа Takahiro Itagaki применил патч:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Добавлены строковые функции: concat(), concat_ws(), left(), right()&lt;br /&gt;и reverse().&lt;br /&gt;&lt;br /&gt;Pavel Stehule, проверено мной.&lt;/code&gt;&lt;br /&gt; &lt;br /&gt;Что это за функции?&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;concat() это просто функциональный аналог оператора || с возможностью обработки нескольких строк за раз:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT concat( &#39;post&#39;, &#39;gres&#39;, &#39;ql&#39; );&lt;br /&gt;   concat   &lt;br /&gt;------------&lt;br /&gt; postgresql&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Очень просто и полезно если надо сделать много конкатенаций.&lt;br /&gt;&lt;br /&gt;concat_ws() похожа, но воспринимает первый аргумент как разделитель:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT concat_ws( &#39; &#39;, &#39;hubert&#39;, &#39;depesz&#39;, &#39;lubaczewski&#39; );&lt;br /&gt;         concat_ws         &lt;br /&gt;---------------------------&lt;br /&gt; hubert depesz lubaczewski&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;left() и right() делают одно и то же, но с разных сторон строки:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT LEFT( &#39;postgresql&#39;, 4 );&lt;br /&gt; LEFT &lt;br /&gt;------&lt;br /&gt; post&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;В общем это работает как substring(), но тут есть одна приятная возможность:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT LEFT( &#39;postgresql&#39;, -2 );&lt;br /&gt;   LEFT   &lt;br /&gt;----------&lt;br /&gt; postgres&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Это значит, что если параметр длинны отрицательный, то функция будет обрезать abs(length) символов с &quot;другой стороны&quot;.&lt;br /&gt;&lt;br /&gt;Примеры для right():&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT RIGHT( &#39;postgresql&#39;, 3 );&lt;br /&gt; RIGHT &lt;br /&gt;-------&lt;br /&gt; sql&lt;br /&gt;(1 row)&lt;br /&gt; &lt;br /&gt;$ SELECT RIGHT( &#39;postgresql&#39;, -4 );&lt;br /&gt; RIGHT  &lt;br /&gt;--------&lt;br /&gt; gresql&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Это всё относительно просто можно было сделать раньше. Но последняя функция, по моему не такому уж скромному мнению, является наиболее важной - reverse(). Её задача тривиальна:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT reverse( &#39;postgresql&#39; );&lt;br /&gt;  reverse   &lt;br /&gt;------------&lt;br /&gt; lqsergtsop&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Но то, что она в ядре PostgreSQL означает что мы теперь можем сделать быстрый (индексный поиск) с условием вида LIKE &#39;%something&#39; (&#39;%&#39; в начале!). Техника для этого была &lt;a href=&quot;http://www.depesz.com/index.php/2007/07/30/indexable-field-like-something/&quot;&gt;описана&lt;/a&gt; ранее, но тогда небыло быстрой reverse().</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/2991796156777725367/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/09/91-concat-concatws-right-left-reverse.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2991796156777725367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2991796156777725367'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/09/91-concat-concatws-right-left-reverse.html' title='В ожидании 9.1 - concat, concat_ws, right, left, reverse'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-1294278142415847543</id><published>2010-09-07T15:26:00.000+04:00</published><updated>2010-09-07T15:26:28.745+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="configuration"/><category scheme="http://www.blogger.com/atom/ns#" term="dialog"/><category scheme="http://www.blogger.com/atom/ns#" term="floating"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><category scheme="http://www.blogger.com/atom/ns#" term="xmonad"/><title type='text'>Правила для окон в XMonad</title><content type='html'>Задача - сделать так чтобы все диалоговые окна, некоторые окна по имени класса, некоторые по заголовку и некоторые по ресурсу появлялись плавающими (floating), т.е. не были &quot;тайловыми&quot;.&lt;br /&gt;&lt;br /&gt;Решение - приводим ~/.xmonad/xmonad.hs в соответствие с нижеследующим примером.&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;code&gt;import XMonad.Hooks.ManageDocks&lt;br /&gt;import XMonad.Hooks.ManageHelpers&lt;br /&gt;...&lt;br /&gt;main = do&lt;br /&gt;  ...&lt;br /&gt;  xmonad $ myUrgencyHook $ defaultConfig {&lt;br /&gt;    ...&lt;br /&gt;    manageHook = myManageHook &lt;+&gt; manageDocks &lt;+&gt; manageHook defaultConfig,&lt;br /&gt;    ...&lt;br /&gt;    }&lt;br /&gt;...&lt;br /&gt;-- Window rules&lt;br /&gt;myManageHook = composeAll . concat $ [&lt;br /&gt;  [isDialog --&gt; doFloat],&lt;br /&gt;  [className =? c --&gt; doFloat | c &lt;- myCFloats],&lt;br /&gt;  [title =? t --&gt; doFloat | t &lt;- myTFloats],&lt;br /&gt;  [resource =? r --&gt; doFloat | r &lt;- myRFloats],&lt;br /&gt;  [resource =? i --&gt; doIgnore | i &lt;- myIgnores]&lt;br /&gt;  ]&lt;br /&gt;  where&lt;br /&gt;    myCFloats = [&quot;Xmessage&quot;]&lt;br /&gt;    myTFloats = [&quot;Save As...&quot;, &quot;Save File&quot;]&lt;br /&gt;    myRFloats = []&lt;br /&gt;    myIgnores = [&quot;XXkb&quot;]&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;В переменную myCFloats прописываем имена всех классов окон, которые нужно отображать плавающими, соответственно в myTFloats заголовки и в myRFloats ресурсы.&lt;br /&gt;&lt;br /&gt;Мою последнюю конфигурацию Xmonad и всё её сопровождающее найдёте здесь &lt;a href=&quot;http://haskell.org/haskellwiki/Xmonad/Config_archive&quot;&gt;Xmonad/Config_archive&lt;/a&gt; (поищите gray_hemp).</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/1294278142415847543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/xmonad.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1294278142415847543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1294278142415847543'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/xmonad.html' title='Правила для окон в XMonad'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-1333007888670836293</id><published>2010-08-18T10:29:00.002+04:00</published><updated>2010-08-18T10:39:41.241+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="process"/><category scheme="http://www.blogger.com/atom/ns#" term="ps"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><category scheme="http://www.blogger.com/atom/ns#" term="shell"/><title type='text'>Уведомить когда процесс остановиться (shell)</title><content type='html'>Это маленький, но очень полезный сниплет, который позволяет сэкономить время и сохранить внимание. Я его использую очень часто, когда жду, например, окончания загрузки чего-то куда-то.&lt;br /&gt;&lt;br /&gt;10708 - pid процесса который мы ждём:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(while [ $(ps -p 10708 ho pid) ]; do sleep 5; done; echo -e &quot;\a&quot;) &amp;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Это работает в бэкграунде, т.ч. можно продолжать пользоваться терминалом.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/1333007888670836293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/shell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1333007888670836293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1333007888670836293'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/shell.html' title='Уведомить когда процесс остановиться (shell)'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-8644115894031444224</id><published>2010-08-11T20:45:00.010+04:00</published><updated>2010-08-12T20:24:20.821+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="group by"/><category scheme="http://www.blogger.com/atom/ns#" term="Hubert Lubaczewski"/><category scheme="http://www.blogger.com/atom/ns#" term="pg91"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="primary key"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>В ожидании 9.1 - Распознавание функциональной зависимости от первичных ключей</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.depesz.com/index.php/2010/08/08/waiting-for-9-1-recognize-functional-dependency-on-primary-keys/&quot;&gt;Waiting for 9.1 – Recognize functional dependency on primary keys&lt;/a&gt; с &lt;a href=&quot;http://www.depesz.com/&quot;&gt;select * from depesz;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Вчера (7 августа) Tom Lane применил:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Распознавание функциональной зависимости от первичных ключей. Это позволяет &lt;br /&gt;колонкам не присутствовать в GROUP BY, если там присутствует первичный ключ.&lt;br /&gt;&lt;br /&gt;В дальнейшем нам стоит также разрешить функциональную зависимость от UNIQUE &lt;br /&gt;ограничений при условии, что колонка помечена как NOT NULL, но это будет ждать пока &lt;br /&gt;NOT NULL ограничения не будут представлены в pg_constraint, т.к. нам будут нужны &lt;br /&gt;pg_constraint OID-ы для всех условий, где будет разрешаться функциональная &lt;br /&gt;зависимость. &lt;br /&gt;&lt;br /&gt;Peter Eisentraut, проверено Alex Hunsaker и Tom Lane&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Одна из наиболее частых проблем, с которой люди сталкиваются при переходе с MySQL на PostgreSQL, заключается вот в таких запросах:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT field_a, field_b, count(*)&lt;br /&gt;FROM TABLE&lt;br /&gt;GROUP BY field_a&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Это нормально для MySQL, но не работало в PostgreSQL. &lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Теперь, с новым патчем, это подмножество запросов будет работать и в PostgreSQL. Во первых, что это за подмножество? Всё просто - если field_a первичный ключ данной таблицы и мы группируем по нему, то очевидно, что мы не получим более чем одной строки и значения field_b для каждого из значений field_a. Но если это не первичный ключ, то может получиться что для каких-то значений field_a будет несколько значений field_b, и в этом случае запрос уже не подходит.&lt;br /&gt;&lt;br /&gt;Рассмотрим пример:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;CREATE TABLE people (&lt;br /&gt;    id serial PRIMARY KEY,&lt;br /&gt;    firstname TEXT,&lt;br /&gt;    lastname TEXT&lt;br /&gt;);&lt;br /&gt; &lt;br /&gt;CREATE TABLE visits (&lt;br /&gt;    id serial PRIMARY KEY,&lt;br /&gt;    person_id INT4 NOT NULL REFERENCES people (id),&lt;br /&gt;    when_logged timestamptz&lt;br /&gt;);&lt;br /&gt; &lt;br /&gt;INSERT INTO people (firstname, lastname)&lt;br /&gt;VALUES&lt;br /&gt;    (&#39;Bill&#39;, &#39;Hicks&#39;),&lt;br /&gt;    (&#39;George&#39;, &#39;Carlin&#39;),&lt;br /&gt;    (&#39;Louis&#39;, &#39;C.K.&#39;),&lt;br /&gt;    (&#39;Robin&#39;, &#39;Williams&#39;),&lt;br /&gt;    (&#39;Zach&#39;, &#39;Galifianakis&#39;);&lt;br /&gt; &lt;br /&gt;INSERT INTO visits (person_id, when_logged)&lt;br /&gt;    SELECT&lt;br /&gt;        1 + floor(random() * 5),&lt;br /&gt;        now() - &#39;1 year&#39;::INTERVAL * random()&lt;br /&gt;    FROM&lt;br /&gt;        generate_series(1,1000);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Теперь положим что надо получить список людей со счётчиками посещений. Ранее надо было делать так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT&lt;br /&gt;    p.id,&lt;br /&gt;    count(*)&lt;br /&gt;FROM&lt;br /&gt;    people p&lt;br /&gt;    JOIN visits v ON p.id = v.person_id&lt;br /&gt;GROUP BY p.id;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Или так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT&lt;br /&gt;    p.id,&lt;br /&gt;    p.firstname,&lt;br /&gt;    p.lastname,&lt;br /&gt;    count(*)&lt;br /&gt;FROM&lt;br /&gt;    people p&lt;br /&gt;    JOIN visits v ON p.id = v.person_id&lt;br /&gt;GROUP BY p.id, p.firstname, p.lastname;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;(или трюкачить с min(firstname))&lt;br /&gt;&lt;br /&gt;Но теперь можно сделать так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT&lt;br /&gt;    p.id,&lt;br /&gt;    p.firstname,&lt;br /&gt;    p.lastname,&lt;br /&gt;    count(*)&lt;br /&gt;FROM&lt;br /&gt;    people p&lt;br /&gt;    JOIN visits v ON p.id = v.person_id&lt;br /&gt;GROUP BY p.id;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;И всё будет прекрасно работать.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/8644115894031444224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/91.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/8644115894031444224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/8644115894031444224'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/91.html' title='В ожидании 9.1 - Распознавание функциональной зависимости от первичных ключей'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-8062805824281961738</id><published>2010-08-11T19:32:00.008+04:00</published><updated>2010-08-11T20:23:28.933+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="alter table"/><category scheme="http://www.blogger.com/atom/ns#" term="Hubert Lubaczewski"/><category scheme="http://www.blogger.com/atom/ns#" term="lock"/><category scheme="http://www.blogger.com/atom/ns#" term="locks"/><category scheme="http://www.blogger.com/atom/ns#" term="pg91"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><category scheme="http://www.blogger.com/atom/ns#" term="trigger"/><title type='text'>В ожидании 9.1 - Снижаем уровни блокировок для ALTER TABLE</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.depesz.com/index.php/2010/08/08/waiting-for-9-1-reduced-lock-levels-for-alter-table/&quot;&gt;Waiting for 9.1 – Reduced lock levels for ALTER TABLE&lt;/a&gt; с &lt;a href=&quot;http://www.depesz.com/&quot;&gt;select * from depesz;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;28 июля Simon Riggs применил патч:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Снижает уровни блокировок CREATE TRIGGER и некоторых действий ALTER TABLE, &lt;br /&gt;CREATE RULE. Убирает прописанные на прямую в коде режимы блокировок, используемые во &lt;br /&gt;множестве команд изменения DDL, позволяя более легко менять уровни блокировок в &lt;br /&gt;будущем. Реализован начальный анализ DDL подкомманд, так что многие уровни блокировок &lt;br /&gt;теперь будут ShareUpdateExclusiveLock или ShareRowExclusiveLock, позволяя конкретным &lt;br /&gt;коммандам не блокировать чтение/запись. Это первое изменение из числа запланированных &lt;br /&gt;в этом направлении; будет нужна дополнительная документация когда весь проект &lt;br /&gt;завершится.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Во первых - это только начало. Конечная цель - сделать все (большинство?) выражения ALTER TABLE менее навязчивыми.&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Ранее все ALTER TABLE блокировали всякий доступ к таблице:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Сессия 1: # begin;&lt;br /&gt;Сессия 2: # begin;&lt;br /&gt;Сессия 1: *# create trigger q after insert on table_name &lt;br /&gt;            for each row execute procedure test();&lt;br /&gt;...тут засыпает на 10 минут...&lt;br /&gt;Сессия 2: *# select * from table_name;&lt;br /&gt;...а тут ждёт 10 минут...&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Это было потому что все ALTER TABLE и CREATE TRIGGER требовали AccessExclusiveLock на таблицу:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;*# create trigger q after insert on table_name for each row execute procedure test();&lt;br /&gt;CREATE TRIGGER&lt;br /&gt; &lt;br /&gt;*# SELECT * FROM pg_locks where pid = pg_backend_pid();&lt;br /&gt;   locktype    | database | relation |  page  | tuple  | virtualxid | transactionid | classid | objid  | objsubid | virtualtransaction | pid  |        mode         | granted&lt;br /&gt;---------------+----------+----------+--------+--------+------------+---------------+---------+--------+----------+--------------------+------+---------------------+---------&lt;br /&gt; virtualxid    |   [null] |   [null] | [null] | [null] | 13/674866  |        [null] |  [null] | [null] |   [null] | 13/674866          | 9492 | ExclusiveLock       | t&lt;br /&gt; relation      |    48535 |    69187 | [null] | [null] | [null]     |        [null] |  [null] | [null] |   [null] | 13/674866          | 9492 | AccessExclusiveLock | t&lt;br /&gt; transactionid |   [null] |   [null] | [null] | [null] | [null]     |        632704 |  [null] | [null] |   [null] | 13/674866          | 9492 | ExclusiveLock       | t&lt;br /&gt; relation      |    48535 |    10969 | [null] | [null] | [null]     |        [null] |  [null] | [null] |   [null] | 13/674866          | 9492 | AccessShareLock     | t&lt;br /&gt;(4 rows)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;И как мы знаем (или &lt;a href=&quot;http://www.postgresql.org/docs/current/interactive/explicit-locking.html#TABLE-LOCK-COMPATIBILITY&quot;&gt;можем найти в документации&lt;/a&gt;) данный тип блокировки конфликтует со всем.&lt;br /&gt;&lt;br /&gt;В 9.1 полученная блокировка будет другой:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;*$ SELECT * FROM pg_locks where pid = pg_backend_pid();&lt;br /&gt;   locktype    | database | relation |  page  | tuple  | virtualxid | transactionid | classid | objid  | objsubid | virtualtransaction |  pid  |         mode          | granted&lt;br /&gt;---------------+----------+----------+--------+--------+------------+---------------+---------+--------+----------+--------------------+-------+-----------------------+---------&lt;br /&gt; transactionid |   [null] |   [null] | [null] | [null] | [null]     |           752 |  [null] | [null] |   [null] | 2/386              | 27199 | ExclusiveLock         | t&lt;br /&gt; relation      |    16398 |    16419 | [null] | [null] | [null]     |        [null] |  [null] | [null] |   [null] | 2/386              | 27199 | ShareRowExclusiveLock | t&lt;br /&gt; virtualxid    |   [null] |   [null] | [null] | [null] | 2/386      |        [null] |  [null] | [null] |   [null] | 2/386              | 27199 | ExclusiveLock         | t&lt;br /&gt; relation      |    16398 |    10987 | [null] | [null] | [null]     |        [null] |  [null] | [null] |   [null] | 2/386              | 27199 | AccessShareLock       | t&lt;br /&gt;(4 rows)&lt;br /&gt; &lt;br /&gt;(depesz@[local]:5900) 15:12:55 [depesz]&lt;br /&gt;*$ select 16419::regclass, 10987::regclass;&lt;br /&gt;  regclass  | regclass&lt;br /&gt;------------+----------&lt;br /&gt; table_name | pg_locks&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;В этот раз мы видим, что CREATE TRIGGER получает только ShareRowExclusiveLock, что разрешает делать SELECT запросы. Операции модификации (UPDATE, INSERT, DELETE) и другие DDL запросы к этой таблице всё ещё не будут разрешены. Но возможность хотя бы делать операции чтения это уже большой выигрыш. &lt;br /&gt;&lt;br /&gt;Я не нашел окончательный список всех вариантов ALTER TABLE, которые получают такой уровень блокировки, но это и не так важно - всё ещё поменяется, и новые варианты будут добавляться. Сейчас я знаю что добавление триггеров и установка значения по умолчанию используют ShareUpdateExclusiveLock вместо AccessExclusiveLock. Что будет следующим - посмотрим.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/8062805824281961738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/91-alter-table.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/8062805824281961738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/8062805824281961738'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/91-alter-table.html' title='В ожидании 9.1 - Снижаем уровни блокировок для ALTER TABLE'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-799170349278520302</id><published>2010-08-11T18:56:00.003+04:00</published><updated>2010-08-11T19:09:45.865+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="column"/><category scheme="http://www.blogger.com/atom/ns#" term="information_schema"/><category scheme="http://www.blogger.com/atom/ns#" term="pgsql-general"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>Как получить имена всех таблиц содержащих колонку с заданным именем</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;На основе обсуждения &lt;a href=&quot;http://archives.postgresql.org/pgsql-general/2010-08/msg00329.php&quot;&gt;filter tables from database&lt;/a&gt; с &lt;a href=&quot;http://archives.postgresql.org/pgsql-general/&quot;&gt;pgsql-general&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Всё очень просто:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT table_name&lt;br /&gt;FROM information_schema.columns&lt;br /&gt;WHERE column_name = &#39;put_column_name_here&#39;;&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/799170349278520302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/799170349278520302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/799170349278520302'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/08/blog-post.html' title='Как получить имена всех таблиц содержащих колонку с заданным именем'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-8596236069562675799</id><published>2010-07-29T20:39:00.004+04:00</published><updated>2010-07-29T21:51:26.796+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="conditional"/><category scheme="http://www.blogger.com/atom/ns#" term="create table"/><category scheme="http://www.blogger.com/atom/ns#" term="ddl"/><category scheme="http://www.blogger.com/atom/ns#" term="Hubert Lubaczewski"/><category scheme="http://www.blogger.com/atom/ns#" term="if not exists"/><category scheme="http://www.blogger.com/atom/ns#" term="pg91"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="sql"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>В ожидании 9.1 - CREATE TABLE IF NOT EXISTS</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.depesz.com/index.php/2010/07/28/waiting-for-9-1-create-table-if-not-exists/&quot;&gt;Waiting for 9.1 – CREATE TABLE IF NOT EXISTS&lt;/a&gt; с &lt;a href=&quot;http://www.depesz.com/&quot;&gt;select * from depesz;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;25 июля Robert Haas применил патч, добавляющий CREATE IF NOT EXISTS для таблиц.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;CREATE TABLE IF NOT EXISTS.&lt;br /&gt;&lt;br /&gt;Reviewed by Bernd Helmle.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Пример тривиален:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ create table if not exists tesit (x text);&lt;br /&gt;CREATE TABLE&lt;br /&gt;&lt;br /&gt;$ create table if not exists tesit (x text);&lt;br /&gt;NOTICE:  relation &quot;tesit&quot; already exists, skipping&lt;br /&gt;CREATE TABLE&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Как можно видеть ошибки нет - просто дружелюбное замечание.&lt;br /&gt;&lt;br /&gt;Скорее всего такое же будет для схем, индексов, вью и других объектов базы, и нам не потребуется больше все эти корявые &lt;a href=&quot;http://www.depesz.com/index.php/2008/06/18/conditional-ddl/&quot;&gt;воркэраунды&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/8596236069562675799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/91-create-table-if-not-exists.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/8596236069562675799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/8596236069562675799'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/91-create-table-if-not-exists.html' title='В ожидании 9.1 - CREATE TABLE IF NOT EXISTS'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-1386630785662872087</id><published>2010-07-26T13:14:00.006+04:00</published><updated>2010-07-26T13:53:27.573+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="generate_series"/><category scheme="http://www.blogger.com/atom/ns#" term="Hubert Lubaczewski"/><category scheme="http://www.blogger.com/atom/ns#" term="order"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><category scheme="http://www.blogger.com/atom/ns#" term="unnest"/><category scheme="http://www.blogger.com/atom/ns#" term="values"/><category scheme="http://www.blogger.com/atom/ns#" term="window functions"/><title type='text'>Как можно задать порядок результата</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.depesz.com/index.php/2010/07/25/how-to-order-by-some-random-query-defined-values/&quot;&gt;How to order by some random - query defined - values?&lt;/a&gt; с &lt;a href=&quot;http://www.depesz.com/&quot;&gt;select * from depesz;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Представим простую ситуацию - есть таблица каких-то объектов (каждый со своим id) откуда надо достать объекты с id 3, 71, 5 и 16. И, самое главное, в том же порядке!&lt;br /&gt;&lt;br /&gt;Как это сделать?&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Во-первых, добавим тестовых данных:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;CREATE TABLE test_data (&lt;br /&gt;    id       INT4 PRIMARY KEY,&lt;br /&gt;    codename TEXT&lt;br /&gt;);&lt;br /&gt;INSERT INTO test_data ( id, codename )&lt;br /&gt;    SELECT i, &#39;codename for: &#39; || i&lt;br /&gt;    FROM generate_series( 1, 100 ) i;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Теперь, чтобы получить эти 4 строки, можно сделать так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT * FROM test_data WHERE id IN (3, 71, 5, 16);&lt;br /&gt; id |     codename     &lt;br /&gt;----+------------------&lt;br /&gt;  3 | codename FOR: 3&lt;br /&gt;  5 | codename FOR: 5&lt;br /&gt; 16 | codename FOR: 16&lt;br /&gt; 71 | codename FOR: 71&lt;br /&gt;(4 rows)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Но, никак нельзя добавить ничего в ORDER BY, чтобы получить их в порядке указанном в IN (...). Итак, что можно сделать. Один способ это использовать (доступные с 8.2) VALUES() следующим образом:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT&lt;br /&gt;    t.*&lt;br /&gt;FROM&lt;br /&gt;    test_data t&lt;br /&gt;    JOIN (&lt;br /&gt;        VALUES&lt;br /&gt;            (1, 3),&lt;br /&gt;            (2, 71),&lt;br /&gt;            (3, 5),&lt;br /&gt;            (4, 16)&lt;br /&gt;        ) AS c (ordering, id) ON t.id = c.id&lt;br /&gt;ORDER BY&lt;br /&gt;    c.ordering;&lt;br /&gt; id |     codename     &lt;br /&gt;----+------------------&lt;br /&gt;  3 | codename FOR: 3&lt;br /&gt; 71 | codename FOR: 71&lt;br /&gt;  5 | codename FOR: 5&lt;br /&gt; 16 | codename FOR: 16&lt;br /&gt;(4 rows)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Всё очень хорошо, только надо указывать дополнительные данные, и их формат не очень хорошо выглядит. К счастью есть другой способ. С 8.4 у нас есть Window Functions и unnest(), т.ч. можно сделать так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;WITH ordered_want AS (&lt;br /&gt;    SELECT&lt;br /&gt;        id,&lt;br /&gt;        row_number() over () AS ordering&lt;br /&gt;    FROM&lt;br /&gt;        unnest( &#39;{3,71,5,16}&#39;::INT4[] ) AS id&lt;br /&gt;)&lt;br /&gt;SELECT&lt;br /&gt;    t.*&lt;br /&gt;FROM&lt;br /&gt;    test_data t&lt;br /&gt;    JOIN ordered_want o ON t.id = o.id&lt;br /&gt;ORDER BY&lt;br /&gt;    o.ordering;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Уже лучше. В этом случае подстановка id-ков осуществляется намного проще - просто укажите массив целых и всё.&lt;br /&gt;&lt;br /&gt;Есть ещё один способ. Если не можете использовать Window Functions, то можно задействовать относительно старый трюк с упорядочиванием по position():&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT&lt;br /&gt;    t.*&lt;br /&gt;FROM&lt;br /&gt;    test_data t&lt;br /&gt;WHERE&lt;br /&gt;    t.id IN (3,71,5,16)&lt;br /&gt;ORDER BY&lt;br /&gt;    position( &#39;,&#39; || t.id || &#39;,&#39; IN &#39;,3,71,5,16,&#39; );&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Тут не забудьте указать пердшествующую и последующую запятые и добавьте их также вокруг t.id в ORDER BY.&lt;br /&gt;&lt;br /&gt;Да, тут будут проблемы, если вы работаете с текстовыми id, но всёже один из вариантов.&lt;br /&gt;&lt;br /&gt;Комментарии:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;# AREK, 25 июня 2010&lt;br /&gt;&lt;br /&gt;Если поставить intarray, то можно упростить последний запрос следующим образом:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT *, idx(‘{3,71,5,16}’, id) AS rank&lt;br /&gt;FROM test_data&lt;br /&gt;WHERE id = ANY(‘{3,71,5,16}’)&lt;br /&gt;ORDER BY rank;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Заметьте также, что вместо IN тут используется = ANY(). Это может быть проблемой для кода приложения, если вы не пишите запросы сами, а просто подставляете значения.&lt;br /&gt;&lt;br /&gt;Что касается текстовых id, то можно написать функцию idx(text[], text) и использовать тот же запрос.&lt;/blockquote&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/1386630785662872087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/blog-post.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1386630785662872087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1386630785662872087'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/blog-post.html' title='Как можно задать порядок результата'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-5688183735064677642</id><published>2010-07-26T12:59:00.003+04:00</published><updated>2010-07-26T13:13:37.085+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="backup"/><category scheme="http://www.blogger.com/atom/ns#" term="David Fetter"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>MVC бэкапы</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://people.planetpostgresql.org/dfetter/index.php?/archives/61-MVC-Backups.html&quot;&gt;MVC Backups&lt;/a&gt; с &lt;a href=&quot;http://people.planetpostgresql.org/dfetter/&quot;&gt;David Fetter&#39;s blog&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Цель - использовать паттерн Model-View-Controller для создания бэкапов на любой платформе, которую поддерживает PostgreSQL.&lt;br /&gt;&lt;br /&gt;Сначала создадим SQL файл, реализующий Model и View:&lt;br /&gt;&lt;br /&gt;backup.sql:&lt;br /&gt;&lt;code&gt;WITH t AS (                                -- Эта часть Model.&lt;br /&gt;    SELECT quote_ident(datname) AS d&lt;br /&gt;    FROM pg_database WHERE NOT datistemplate&lt;br /&gt;)&lt;br /&gt;SELECT&lt;br /&gt;    &#39;pg_dump -U postgres -Fc --file=&#39; || d ||   -- Эта часть View.&lt;br /&gt;     to_char(now(),&#39;_YYYYMMDD&#39;) ||&lt;br /&gt;    &#39;.pgbackup&#39; || &#39; &#39;|| d&lt;br /&gt;FROM t;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Затем реализуем Controller.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;psql -Atqf backup.sql | sh&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Заметьте, если вы на Windows, то можете подставить cmd.exe или command.com как sh.&lt;br /&gt;&lt;br /&gt;Готово!</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/5688183735064677642/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/mvc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/5688183735064677642'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/5688183735064677642'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/mvc.html' title='MVC бэкапы'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-969143279086662812</id><published>2010-07-22T11:29:00.004+04:00</published><updated>2010-07-29T21:53:13.459+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="conninfo"/><category scheme="http://www.blogger.com/atom/ns#" term="Hubert Lubaczewski"/><category scheme="http://www.blogger.com/atom/ns#" term="pg91"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="psql"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>В ожидании 9.1 - \conninfo в psql</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.depesz.com/index.php/2010/07/21/waiting-for-9-1-conninfo-in-psql/&quot;&gt;Waiting for 9.1 – \conninfo in psql&lt;/a&gt; с &lt;a href=&quot;http://www.depesz.com/&quot;&gt;select * from depesz;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;20 июля Robert Haas применил патч, добавляющий ещё одну \* комманду в psql:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Добавляет команду \conninfo в psql, показывающую информацию о текущем соединении.&lt;br /&gt;&lt;br /&gt;David Christensen. Проверено Steve Singer. Некоторые изменения от меня.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Из сообщения всё предельно понятно, т.ч. просто посмотрим на это:&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;code&gt;$ \conninfo&lt;br /&gt;&lt;br /&gt;You are connected to database &quot;depesz&quot; via local socket at port &quot;5900&quot; as user &quot;depesz&quot;.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Это полезно тем, кто работает с несколькими базами данных - просто для того чтобы по ошибке не запустить SQL не на той базе.&lt;br /&gt;&lt;br /&gt;Ранее подобный эффект можно было получить добавив следующее в $HOME/.psqlrc:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;\set PROMPT1 &#39;(%n@%M:%&gt;) %`date +%H:%M:%S` [%/] \n%x$ &#39;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Благодаря этому моя подсказка выглядит так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(depesz@[local]:5900) 14:57:43 [depesz]&lt;br /&gt;$&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Т.о. у меня есть нужная информация без ввода доп. комманд. В любом случае, новая возможность полезна, если вы не можете (или не хотите) менять окружение.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/969143279086662812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/91-conninfo-psql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/969143279086662812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/969143279086662812'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/91-conninfo-psql.html' title='В ожидании 9.1 - \conninfo в psql'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-1659248567010570643</id><published>2010-07-22T10:42:00.007+04:00</published><updated>2010-07-29T21:53:46.179+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Hubert Lubaczewski"/><category scheme="http://www.blogger.com/atom/ns#" term="pg91"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="sql-standart"/><category scheme="http://www.blogger.com/atom/ns#" term="strings"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>В ожидании 9.1 - standard_conforming_strings = on</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://www.depesz.com/index.php/2010/07/21/waiting-for-9-1-standard_conforming_strings-on/&quot;&gt;Waiting for 9.1 – standard_conforming_strings = on&lt;/a&gt; с &lt;a href=&quot;http://www.depesz.com/&quot;&gt;select * from depesz;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;В основном я пишу о новых возможностях, но это изменение довольно таки важное.&lt;br /&gt;&lt;br /&gt;20 июля Robert Haas сделал следующие изменения:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Значение standard_conforming_strings по умолчанию теперь on.&lt;br /&gt;&lt;br /&gt;Это изменение должно быть доведено до сведения разработчиков драйверов и в &lt;br /&gt;замечаниях к релизу должно быть указанным как не совместимое с предыдущими &lt;br /&gt;релизами.&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Что это и почему так важно?&lt;br /&gt;Допустим вы хотите выбрать какое-то значение содержащее символ &#39; (апостроф). Т.к. строки тоже определяются этим символом нам нужно замаскировать его.&lt;br /&gt;&lt;br /&gt;Долгое время можно было делать так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT &#39;guns \&#39;n roses&#39;;&lt;br /&gt;   ?COLUMN?    &lt;br /&gt;---------------&lt;br /&gt; guns &#39;n roses&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Это выглядит нормально для любого программиста, работающего на другом языке, но у нас есть небольшая проблема - SQL стандарт это не приемлет.&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Некоторое время назад, не помню когда точно, да и это не так важно, PostgreSQL представил маскированые строковые константы, которые выглядят так: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT E&#39;guns \&#39;n roses&#39;;&lt;br /&gt;   ?COLUMN?    &lt;br /&gt;---------------&lt;br /&gt; guns &#39;n roses&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;И когда вы используете обычные строки с маскированием обратной косой чертой, он выдаёт предупреждение:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT &#39;guns \&#39;n roses&#39;;&lt;br /&gt;WARNING:  nonstandard USE of \&#39; in a string literal&lt;br /&gt;LINE 1: select &#39;guns \&#39;n roses&#39;;&lt;br /&gt;               ^&lt;br /&gt;HINT:  USE &#39;&#39; TO WRITE quotes IN strings, OR USE the escape string syntax (E&#39;...&#39;).&lt;br /&gt;   ?COLUMN?    &lt;br /&gt;---------------&lt;br /&gt; guns &#39;n roses&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Т.е. всё работает так же как и раньше, только добавилось это предупреждение. Конечно же оно (предупреждение) может быть отключено (escape_string_warning GUC), и вы можете запретить маскирование установив standard_conforming_strings в on.&lt;br /&gt;&lt;br /&gt;Теперь, в 9.1, standard_conforming_strings будет по умолчанию on. А это значит, что с нашим тестом случится следующее:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT &#39;guns \&#39;n roses&#39;;&lt;br /&gt;&amp;gt;&amp;gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;PostgreSQL теперь трактует \ как обычный символ, и т.к. кол-во апострофов нечётное значит что одна из строк ещё не завержена и запрос ещё не готов.&lt;br /&gt;&lt;br /&gt;Простой пример:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT &#39;first line\nsecond line&#39;;&lt;br /&gt;  ?COLUMN?&lt;br /&gt;-------------&lt;br /&gt; first line +&lt;br /&gt; second line&lt;br /&gt;(1 row)&lt;br /&gt; &lt;br /&gt;$ SET standard_conforming_strings = ON;&lt;br /&gt;SET&lt;br /&gt; &lt;br /&gt;$ SELECT &#39;first line\nsecond line&#39;;&lt;br /&gt;        ?COLUMN?&lt;br /&gt;-------------------------&lt;br /&gt; first line\nsecond line&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Итак, как теперь писать запросы с апострофами и символами новой строки? Короткий ответ - делать это правильно. Пример:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$ SELECT &#39;guns &#39;&#39;n roses&#39;;&lt;br /&gt;   ?COLUMN?&lt;br /&gt;---------------&lt;br /&gt; guns &#39;n roses&lt;br /&gt;(1 row)&lt;br /&gt; &lt;br /&gt;$ select E&#39;first line\nsecond line&#39;;&lt;br /&gt;  ?column?&lt;br /&gt;-------------&lt;br /&gt; first line +&lt;br /&gt; second line&lt;br /&gt;(1 row)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Если вы пишите запросы сами, это не большая проблема, но если используете что-то что строит их за вас (ORM или что-то формирующее параметры) - это должно быть исправлено (если не было исправлено ранее). &lt;br /&gt;&lt;br /&gt;Конечно же можно изменить standard_conforming_strings обратно в off, но это не будет нормальным решением.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/1659248567010570643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/91-standardconformingstrings-on.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1659248567010570643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/1659248567010570643'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/07/91-standardconformingstrings-on.html' title='В ожидании 9.1 - standard_conforming_strings = on'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-6462240913747863746</id><published>2010-06-07T14:27:00.006+04:00</published><updated>2010-07-22T10:40:39.096+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="configuration"/><category scheme="http://www.blogger.com/atom/ns#" term="dired"/><category scheme="http://www.blogger.com/atom/ns#" term="emacs"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><title type='text'>Скрываем dot-файлы в Dired (Emacs)</title><content type='html'>Если пользуетесь Dired, то наверняка часто сталкивались с проблемой, когда, допустим, в вашем &quot;хоуме&quot; (~/) глаза разбегались от обилия dot-файлов (.filename). Действительно так очень неудобно, но есть решение - просто добавьте этот сниплет в конфигурацию:&lt;br /&gt;&lt;br /&gt;~/.emacs.d/general.el:&lt;br /&gt;&lt;code&gt;;; Dired Mode extra features&lt;br /&gt;(load &quot;dired-x.el&quot;)&lt;br /&gt;(setq dired-omit-files&lt;br /&gt;      (concat dired-omit-files &quot;\\|^\\..+$&quot;))&lt;br /&gt;(dired-omit-mode 1)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;По умолчанию он выключает отображение dot-файлов. Чтобы переключать режим отображения используйте M-o.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/6462240913747863746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/06/dot-dired-emacs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/6462240913747863746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/6462240913747863746'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/06/dot-dired-emacs.html' title='Скрываем dot-файлы в Dired (Emacs)'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-5071160137543355365</id><published>2010-04-27T03:51:00.010+04:00</published><updated>2010-04-27T12:03:34.521+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="londiste"/><category scheme="http://www.blogger.com/atom/ns#" term="pgq"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="replication"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><category scheme="http://www.blogger.com/atom/ns#" term="skytools"/><title type='text'>Установка Londiste в подробностях</title><content type='html'>Этот пост содержит подробное пошаговое описание процесса настройки репликации на основе Londiste, системы асинхронной мастер-слэйв репликации из пакета SkyTools от Skype.&lt;br /&gt;&lt;br /&gt;Допустим есть 2 сервера - host1 и host2. На host1 работает кластер с одной или несколькими базами, которые необходимо реплицировать на host2. Другими словами host1 будет мастером, а host2 слейвом.&lt;br /&gt;&lt;br /&gt;Прежде всего необходимо установить пакет SkyTools. Его исходники можно найти на &lt;a href=&quot;https://developer.skype.com/SkypeGarage/DbProjects/SkyTools&quot;&gt;официальном сайте проекта&lt;/a&gt; или в &lt;a href=&quot;http://wiki.postgresql.org/wiki/Skytools&quot;&gt;wiki&lt;/a&gt;. Там же найдёте всю документацию и ссылки на дополнительные материалы. Советую обращаться к ним если захотите узнать дополнительные подробности о вещах, которых я буду в данной статье касаться поверхностно.&lt;br /&gt;&lt;br /&gt;Итак, всё ПО необходимое для репликации установлено, но, прежде чем начать настройку, хочу рассказать о принципах работы Londiste в очень общих словах.&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;Londiste базируется на механизме очередей PgQ, который тоже входит в пакет SkyTools. Информация об изменениях данных попадает в эти очереди из спец-триггеров, навешиваемых на реплицируемые таблицы. PgQ, в свою очередь, основывается на пакетной обработке и использует так называемый ticker, утилиту (демон), генерирующую события готовности пачек данных. Эти события слушает демон Londiste и по их наступлению переносит пачки с мастера на слейв.&lt;br /&gt;&lt;br /&gt;Репликация на базе Londiste может работать по схеме - один мастер на несколько слейвов. В связи с этим я буду делать пометки, различающие установку репликации первого слейва и последующих. Также я буду различать репликацию отдельной базы и кластера целиком.&lt;br /&gt;&lt;br /&gt;Описанный процесс не требует даунтайма.&lt;br /&gt;&lt;br /&gt;Замечание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;В данном описании будут часто встречаются обобщения более узких ситуаций, которые не тестировались во всех возможных вариантах. Так что прежде чем внедрять её в продакшн, тщательно протестируйте ваш процесс. Если вы найдёте какую-нибудь ошибку или не рабочую ситуацию, буду благодарен если сообщите.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;1. Первым делом подготовим мастер-сервер&lt;br /&gt;&lt;br /&gt;Замечание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Пропустите этот пункт если репликация мастер-сервера уже есть.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;1.1. Права на мастере&lt;br /&gt;&lt;br /&gt;В данном примере все утилиты будут работать под системным пользователем postgres. Операции с БД я доверю также пользователю postgres (который в базе). Но в реальности будет правильнее сделать отдельного пользователя для этих утилит, смотрите по вашей ситуации.&lt;br /&gt;&lt;br /&gt;Дадим пользователю postgres доверительный доступ (без пароля) к базам на мастере со слейва.&lt;br /&gt;&lt;br /&gt;/var/lib/postgres/8.4/data/pg_hba.conf:&lt;br /&gt;&lt;code&gt;...&lt;br /&gt;# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD&lt;br /&gt;                                # host2 IP&lt;br /&gt;host    db1         postgres    192.168.10.2/32       trust&lt;br /&gt;...&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Если реплицируются конкретные базы, а не весь инстанс, то добавьте такие записи для каждой из них. В случае же репликации всего инстанса достаточно одной записи, где в колонке DATABASE указываем all. Не забудьте сделать reload серверу.&lt;br /&gt;&lt;br /&gt;1.2. Настрока ticker-а&lt;br /&gt;&lt;br /&gt;Далее создадим файл конфигурации ticker-а.&lt;br /&gt;&lt;br /&gt;/etc/skytools/db1-ticker.ini:&lt;br /&gt;&lt;code&gt;[pgqadm]&lt;br /&gt;job_name = db1-ticker&lt;br /&gt;db = dbname=db1&lt;br /&gt;&lt;br /&gt;# Задержка между запусками обслуживания (ротация очередей и т.п.) в секундах&lt;br /&gt;maint_delay = 600&lt;br /&gt;&lt;br /&gt;# Задержка между проверками наличия активности (новых пакетов данных) в секундах&lt;br /&gt;loop_delay = 0.1&lt;br /&gt;logfile = /var/log/skytools/%(job_name)s.log&lt;br /&gt;pidfile = /var/run/skytools/%(job_name)s.pid&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Создайте подобные конфигурации для каждой реплицируемой базы. &lt;br /&gt;&lt;br /&gt;1.3. Запускаем ticker&lt;br /&gt;&lt;br /&gt;Теперь необходимо инсталлировать служебный код (SQL) и запустить ticker как демона для каждой из баз. Делается это с помощью утилиты pgqadm.py следующими командами:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python pgqadm.py /etc/skytools/db1-ticker.ini install&lt;br /&gt;python pgqadm.py /etc/skytools/db1-ticker.ini ticker -d&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Проверим, что в логах (/var/log/skytools/db1-tickers.log) всё нормально. На данном этапе там должны быть редкие записи (раз в минуту).&lt;br /&gt;&lt;br /&gt;2. Далее настроим слейв&lt;br /&gt;&lt;br /&gt;2.1. Убедимся что Londiste остановлен&lt;br /&gt;&lt;br /&gt;Замечание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Это действие необходимо если вы раньше работали с Londiste на этом слейве.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py -s /etc/skytools/db1-londiste.ini&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Повторите для всех реплицируемых баз.&lt;br /&gt;&lt;br /&gt;2.2. Востанавливаем схему базы&lt;br /&gt;&lt;br /&gt;Замечание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;В данном примере подразумевается что целевой инстанс не содержит баз с такими же именами как у реплицируемых.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Если реплицируются отдельные базы, то прежде всего необходимо &lt;a href=&quot;http://www.postgresql.org/docs/8.4/interactive/sql-createrole.html&quot;&gt;создать пользователей&lt;/a&gt;, идентичных тем, которые работали с ними на мастере. Далее переносим схемы этих баз на слейв (повторяем для каждой):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;pg_dump -s -C -h host1 -U postgres db1 | &lt;br /&gt;psql -U postgres 1&gt;db1-restore.stdout 2&gt;db2-restore.stderr&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Если реплицируем инстанс целиком, то достаточно один раз сделать так:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;pg_dumpall -s -h host1 -U postgres | &lt;br /&gt;psql -U postgres 1&gt;all-restore.stdout 2&gt;all-restore.stderr&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Убедимся, что в лог-файлах *-restore.stderr отсутствуют ошибки кроме &quot;роль postgres уже существует&quot; (ч.г. не могу понять для чего вообще pg_dumpall дампит эту роль). &lt;br /&gt;&lt;br /&gt;2.3. Создаём конфигурацию репликатора &lt;br /&gt;&lt;br /&gt;Для каждой из реплицируемых баз создадим конфигурационные файлы:&lt;br /&gt;&lt;br /&gt;/etc/skytools/db1-londiste.ini:&lt;br /&gt;&lt;code&gt;[londiste]&lt;br /&gt;job_name = db1-londiste&lt;br /&gt;&lt;br /&gt;provider_db   = dbname=db1 port=5432 host=host1&lt;br /&gt;subscriber_db = dbname=db1&lt;br /&gt;&lt;br /&gt;# Это будет использоваться в качестве SQL-идентификатора, т.ч. не используйте&lt;br /&gt;# точки и пробелы.&lt;br /&gt;# ВАЖНО! Если есть живая репликация на другой слейв, именуем очередь так-же&lt;br /&gt;pgq_queue_name = db1-londiste-queue&lt;br /&gt;&lt;br /&gt;logfile = /var/log/skytools/%(job_name)s.log&lt;br /&gt;pidfile = /var/run/skytools/%(job_name)s.pid&lt;br /&gt;&lt;br /&gt;log_size = 5242880&lt;br /&gt;log_count = 3&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;2.4. Устанавливаем Londiste в базы на мастере и слейве&lt;br /&gt;&lt;br /&gt;Теперь необходимо установить служебный SQL для каждой из созданных в предыдущем пункте конфигураций.&lt;br /&gt;&lt;br /&gt;Устанавливаем код на стороне мастера:&lt;br /&gt;&lt;br /&gt;Замечание: &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Если установка Londiste на эту базу мастера уже была то для него не делаем.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini provider install&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;и подобным образом на стороне слейва:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini subscriber install&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;После этого пункта на мастере будут созданы очереди для репликации. &lt;br /&gt;&lt;br /&gt;2.5. Запускаем процессы Londiste&lt;br /&gt;&lt;br /&gt;Для каждой реплицируемой базы делаем:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini replay -d&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Таким образом запустятся слушатели очередей репликации, но, т.к. мы ещё не указывали какие таблицы хотим реплицировать, они пока будут работать в холостую. &lt;br /&gt;&lt;br /&gt;Убедимся что в логах нет ошибок (/var/log/skytools/db1-londistes.log).&lt;br /&gt;&lt;br /&gt;2.6. Добавляем реплицируемые таблицы&lt;br /&gt;&lt;br /&gt;Для каждой конфигурации указываем что будем реплицировать с мастера:&lt;br /&gt;&lt;br /&gt;Замечание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Если указывали эти таблицы на мастере для другой репликации, то на мастере не делать.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini provider add --all&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;и что со слейва:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini subscriber add --all&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;В данном примере я использую спец-параметр --all, который означает все таблицы, но вместо него вы можете перечислить список конкретных таблиц, если не хотите реплицировать все.&lt;br /&gt;&lt;br /&gt;2.7. Добавляем реплицируемые последовательности (sequence)&lt;br /&gt;&lt;br /&gt;Так же для всех конфигураций.&lt;br /&gt;&lt;br /&gt;Для мастера:&lt;br /&gt;&lt;br /&gt;Замечание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Опять же, если они уже добавлены на мастере, то не добавляем их там.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini provider add-seq --all&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Замечание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;В версиях SkyTools до 2.1.9 включительно был обнаружен баг при добавлением последовательностей на мастере используя параметр --all, т.ч. если у вас такая версия используйте следующий хак:&lt;br /&gt; &lt;br /&gt;&lt;code&gt;for seq in $(&lt;br /&gt;  psql -t -A -U postgres toozla -c &quot;\ds&quot; |&lt;br /&gt;  awk -F &#39;|&#39; &#39;{ if ($1 != &quot;pgq&quot; &amp;&amp; $1 != &quot;londiste&quot;) { print $1&quot;.&quot;$2 } }&#39;); &lt;br /&gt;do&lt;br /&gt;  python londiste.py /etc/skytools/db1-londiste.ini provider add-seq $seq; &lt;br /&gt;done&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Для слейва:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini subscriber add-seq --all&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Точно также как и с таблицами можно указать конкретные последовательности вместо --all.&lt;br /&gt;&lt;br /&gt;2.8. Проверка&lt;br /&gt;&lt;br /&gt;Итак, всё что надо сделано. Теперь Londiste запустит так называемый bulk copy процесс, который массово (с помощью COPY) зальёт присутствующие на момент добавления таблиц данные на слейв, а затем перейдёт в состояние обычной репликации.&lt;br /&gt;&lt;br /&gt;Мониторим логи на предмет ошибок:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;less /var/log/skytools/db1-londiste.log&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Если всё хорошо, смотрим состояние репликации. Данные уже синхронизированы для тех таблиц, где статус отображается как &quot;ok&quot;.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;python londiste.py /etc/skytools/db1-londiste.ini subscriber tables&lt;br /&gt;&lt;br /&gt;Table                                           State&lt;br /&gt;public.table1                                      ok&lt;br /&gt;public.table2                                      ok&lt;br /&gt;public.table3                                 in-copy&lt;br /&gt;public.table4                                       -&lt;br /&gt;public.table5                                       -&lt;br /&gt;public.table6                                       -&lt;br /&gt;...&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Для удобства представляю следующий трюк с уведомление в почту об окончании первоначального копирования (мыло поменять на своё ;):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(&lt;br /&gt;  while [ $(&lt;br /&gt;    python londiste.py /etc/skytools/db1-londiste.ini subscriber tables |&lt;br /&gt;    tail -n+2 | awk &#39;{print $2}&#39; | grep -v ok | wc -l) -ne 0 ];&lt;br /&gt;  do sleep 60; done; echo &#39;&#39; | mail -s &#39;Replication done EOM&#39; user@domain.com&lt;br /&gt;) &amp;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Ссылки на публикации, которые мне помогли в написании этой статьи:&lt;br /&gt;&lt;br /&gt;SkyTools - PostgreSQL Wiki&lt;br /&gt;&lt;a href=&quot;http://wiki.postgresql.org/wiki/Skytools&quot;&gt;http://wiki.postgresql.org/wiki/Skytools&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;SkyTools - Skype Developer Zone&lt;br /&gt;&lt;a href=&quot;https://developer.skype.com/SkypeGarage/DbProjects/SkyTools&quot;&gt;https://developer.skype.com/SkypeGarage/DbProjects/SkyTools&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;PostgreSQL master slave(s) asynchronous replication - tail -f /dev/dim&lt;br /&gt;&lt;a href=&quot;http://tapoueh.org/skytools.html&quot;&gt;http://tapoueh.org/skytools.html&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/5071160137543355365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/londiste.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/5071160137543355365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/5071160137543355365'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/londiste.html' title='Установка Londiste в подробностях'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-3170484526922763840</id><published>2010-04-14T22:48:00.004+04:00</published><updated>2010-04-14T23:22:07.047+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bruce Momjian"/><category scheme="http://www.blogger.com/atom/ns#" term="nosql"/><category scheme="http://www.blogger.com/atom/ns#" term="performance"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>Перенимаем NoSQL</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://momjian.us/main/blogs/pgblog/2010.html#April_10_2010_2&quot;&gt;Learning from NoSQL&lt;/a&gt; с &lt;a href=&quot;http://momjian.us/main/blogs/pgblog/2010.html&quot;&gt;Bruce Momjian: Postgres Blog&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Я думаю, что первый урок, который PostgreSQL сообщество может вынести из NoSQL, в том, что не всем нужны все наши возможности, и, если это не будет сложно, нам необходимо дать пользователям возможность отказаться от некоторых из них, в пользу желаемых NoSQL преимуществ. В некоторых случаях мы уже можем это сделать:&lt;br /&gt;&lt;br /&gt;- Вы можете улучшить скорость за счёт откладывания или отказа от надежности (synchronous_commit, fsync)&lt;br /&gt;- Вы можете убрать затраты на целостность не устанавливая ограничения (constraints)&lt;br /&gt;- Можете использовать подготовленные (prepared) запросы для устранения затрат на парсера и оптимизатора&lt;br /&gt;- Массивы часто могут быть использованы для ухода от затрат на join&lt;br /&gt;- Можно хранить не структурированные данные в hstore&lt;br /&gt;- Устаревшие данные можно обслуживать с помощью асинхронной мульти-мастер репликации (Bucardo)&lt;br /&gt;&lt;br /&gt;Однако есть некоторые вещи, которые будет сложно осуществить:&lt;br /&gt;&lt;br /&gt;- Доступ к данным без SQL&lt;br /&gt;- Снижение затрат за счёт отказа от атомарности и изоляции&lt;br /&gt;&lt;br /&gt;Я думаю о новых опциональных возможностях, которые мы могли бы предоставлять потенциальным NoSQL пользователям, но тут надо всё хорошо продумывать.&lt;br /&gt;&lt;br /&gt;Дополнение: Один из пунктов в нашем TODO-листе, который может помочь потенциальным NoSQL пользователям, это реализация встроенного типа данных JSON. JSON используется в качестве формата хранилища во многих NoSQL базах.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/3170484526922763840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/nosql_14.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/3170484526922763840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/3170484526922763840'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/nosql_14.html' title='Перенимаем NoSQL'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-9195796115899563255</id><published>2010-04-14T22:14:00.003+04:00</published><updated>2010-04-14T22:47:31.977+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bruce Momjian"/><category scheme="http://www.blogger.com/atom/ns#" term="cassandra"/><category scheme="http://www.blogger.com/atom/ns#" term="mongodb"/><category scheme="http://www.blogger.com/atom/ns#" term="nosql"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="translation"/><title type='text'>Несколько слов о NoSQL</title><content type='html'>&lt;span style=&quot;font-style:italic;&quot;&gt;Перевод &lt;a href=&quot;http://momjian.us/main/blogs/pgblog/2010.html#April_10_2010&quot;&gt;Settling for NoSQL&lt;/a&gt; с &lt;a href=&quot;http://momjian.us/main/blogs/pgblog/2010.html&quot;&gt;Bruce Momjian: Postgres Blog&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;В последнее время вокруг NoSQL баз данных довольно много шума, и, багодаря посещению конференции &lt;a href=&quot;http://phillyemergingtech.com/&quot;&gt;Emerging Technologies for the Enterprise Conference&lt;/a&gt;, я узнал о них больше. Я прослушал рассказ о &lt;a href=&quot;https://docs.google.com/viewer?url=http://cbcg.net/talks/Cassandra-PL.pdf&quot;&gt;Cassandra&lt;/a&gt;, и ещё один о &lt;a href=&quot;http://dirolf.com/2010/04/09/introduction-to-mongodb.html&quot;&gt;MongoDB&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;NoSQL базы имеют несколько отличий от реляционных:&lt;br /&gt;&lt;br /&gt;- &quot;голое&quot; обращение к данным, другими словами отсутствие языка запросов (клиент делает большинство того, что обычно делается с помощью SQL)&lt;br /&gt;- отсутствие join-ов (данные должны соединяться на стороне клиента)&lt;br /&gt;- жертвуется ACID и транзакционные свойства ради скорости, отказоустойчивости, простоты добавления/выведения нод&lt;br /&gt;&lt;br /&gt;Кого-то может смутить отсутствие этих значительных возможностей реляционных баз, но, если нужный вам отклик и требования к инфраструктуре не вписываются в рамки реляционных баз, и вы можете принять такие ограничения (думаю социальные медиа или поисковые движки), тогда NoSQL вполне имеет смысл.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/9195796115899563255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/nosql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/9195796115899563255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/9195796115899563255'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/nosql.html' title='Несколько слов о NoSQL'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-6826080981454490025</id><published>2010-04-12T10:33:00.005+04:00</published><updated>2010-04-12T17:06:59.588+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cursor"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="rule"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Vhubuo"/><category scheme="http://www.blogger.com/atom/ns#" term="view"/><title type='text'>Как передать NEW из правила в хранимую функцию.</title><content type='html'>Всё началось на форуме &lt;a href=&quot;http://www.sql.ru/forum/actualtopics.aspx?bid=7&quot;&gt;sql.ru - PostgreSQL&lt;/a&gt;. Вопрос был следующим:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;a href=&quot;http://www.sql.ru/forum/actualthread.aspx?tid=749450&quot;&gt;Как передать NEW из правила в хранимую функцию?&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Описание:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Есть много представлений, в которых в базу записывается, например, адрес. И это везде происходит одинаково. Хочется вынести этот процесс в отдельную процедуру.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://www.dimka.lv/programmirovanie/postgresql-kak-peredat-new-iz-pravila-v-funkciyu/&quot;&gt;Интересное генерализирующее решение&lt;/a&gt; на основе курсоров сегодня в своём блоге опубликовал автор этого вопроса - Vhubuo. Очень не обычный подход.&lt;br /&gt;&lt;br /&gt;А вы бы как это сделали?</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/6826080981454490025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/new.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/6826080981454490025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/6826080981454490025'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/new.html' title='Как передать NEW из правила в хранимую функцию.'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-2934421338394571245</id><published>2010-04-07T20:09:00.006+04:00</published><updated>2010-04-07T20:58:18.519+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="junction"/><category scheme="http://www.blogger.com/atom/ns#" term="pg_xlog"/><category scheme="http://www.blogger.com/atom/ns#" term="postgresql"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><category scheme="http://www.blogger.com/atom/ns#" term="windows"/><title type='text'>Переносим pg_xlog на другой диск под Windows</title><content type='html'>На днях на форуме &lt;a href=&quot;http://www.sql.ru/forum/actualtopics.aspx?bid=7&quot;&gt;sql.ru - PostgreSQL&lt;/a&gt; был задан вопрос &lt;a href=&quot;http://www.sql.ru/forum/actualthread.aspx?tid=748766&quot;&gt;о переносе pg_xlog под Windows&lt;/a&gt;. Т.к. вопрос актуален для России - 1С, Windows сервера, и т.п., решил сделать этот пост.&lt;br /&gt;&lt;br /&gt;Собственно особенность прцедуры переноса лишь в одном - символические ссылки.&lt;br /&gt;&lt;br /&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;В Linux это делается просто встроенной командой &quot;ln -s ...&quot;, а под Windows для их создания будет нужна &lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx&quot;&gt;вот эта программа (Junction)&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Итак, опишу сам процесс по шагам. Допустим директория pgdata на диске D, и необходимо вынести WAL (pg_xlog) на диск C.&lt;br /&gt;&lt;br /&gt;Для этого надо:&lt;br /&gt;&lt;br /&gt;1. Остановить postgres&lt;br /&gt;2. Сделать бэкап D:\pgdata\pg_xlog&lt;br /&gt;3. Скопировать D:\pgdata\pg_xlog в C:\pg_xlog и удалить D:\pgdata\pg_xlog&lt;br /&gt;4. Распаковать программу &lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx&quot;&gt;junction&lt;/a&gt; в D:\pgdata&lt;br /&gt;5. Открыть окно cmd, перейти там в D:\pgdata и выполнить junction -s pg_xlog C:\pg_xlog&lt;br /&gt;6. Теперь кликаем правой кнопкой на папке C:\pg_xlog и устанавливаем права на неё  пользователю postgres&lt;br /&gt;7. Запускаем postgres&lt;br /&gt;&lt;br /&gt;Вот и всё.</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/2934421338394571245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/pgxlog-windows.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2934421338394571245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2934421338394571245'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/pgxlog-windows.html' title='Переносим pg_xlog на другой диск под Windows'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-193160215117996166.post-2276414378120244389</id><published>2010-04-05T19:36:00.003+04:00</published><updated>2010-04-06T02:57:57.045+04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="buffers"/><category scheme="http://www.blogger.com/atom/ns#" term="pg_buffercache"/><category scheme="http://www.blogger.com/atom/ns#" term="q and a"/><category scheme="http://www.blogger.com/atom/ns#" term="russian"/><category scheme="http://www.blogger.com/atom/ns#" term="Sergey Konoplev"/><title type='text'>Использование страниц разделяемой памяти</title><content type='html'>&lt;i&gt;Требуется расширение pg_buffercache.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Запрос помогает понять как используется разделяемая память разными сущностями.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;SELECT&lt;br /&gt;    c.relname, -- отношение&lt;br /&gt;    count(*) AS pages, -- количество страниц&lt;br /&gt;    -- использование страниц&lt;br /&gt;    sum((usagecount = 0)::int4) as &quot;0&quot;,&lt;br /&gt;    sum((usagecount = 1)::int4) as &quot;1&quot;,&lt;br /&gt;    sum((usagecount = 2)::int4) as &quot;2&quot;,&lt;br /&gt;    sum((usagecount = 3)::int4) as &quot;3&quot;,&lt;br /&gt;    sum((usagecount = 4)::int4) as &quot;4&quot;,&lt;br /&gt;    sum((usagecount = 5)::int4) as &quot;5&quot;&lt;br /&gt;FROM&lt;br /&gt;    pg_buffercache b&lt;br /&gt;    INNER JOIN pg_class c ON&lt;br /&gt;        b.relfilenode = c.relfilenode AND&lt;br /&gt;        b.reldatabase IN (&lt;br /&gt;            0, (SELECT oid FROM pg_database WHERE datname = current_database())&lt;br /&gt;        )&lt;br /&gt;GROUP BY c.relname&lt;br /&gt;ORDER BY 2 DESC&lt;br /&gt;LIMIT 10;&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='http://gray-hemp.blogspot.com/feeds/2276414378120244389/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2276414378120244389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/193160215117996166/posts/default/2276414378120244389'/><link rel='alternate' type='text/html' href='http://gray-hemp.blogspot.com/2010/04/blog-post.html' title='Использование страниц разделяемой памяти'/><author><name>grayhemp</name><uri>http://www.blogger.com/profile/10468769612315616319</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>