<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="cs">
	<id>http://postgres.cz/index.php?action=history&amp;feed=atom&amp;title=PostgreSQL_9.2_%282012%29</id>
	<title>PostgreSQL 9.2 (2012) - Historie editací</title>
	<link rel="self" type="application/atom+xml" href="http://postgres.cz/index.php?action=history&amp;feed=atom&amp;title=PostgreSQL_9.2_%282012%29"/>
	<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;action=history"/>
	<updated>2026-05-12T22:42:40Z</updated>
	<subtitle>Historie editací této stránky</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=1336&amp;oldid=prev</id>
		<title>PavelStehule v 22. 7. 2025, 16:05</title>
		<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=1336&amp;oldid=prev"/>
		<updated>2025-07-22T16:05:23Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;cs&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Starší verze&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Verze z 22. 7. 2025, 16:05&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l502&quot;&gt;Řádek 502:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Řádek 502:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;DPL&amp;gt;category=Verze PostgreSQL&amp;lt;/DPL&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;DPL&amp;gt;category=Verze PostgreSQL&amp;lt;/DPL&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Články]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Články]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Verze PostgreSQL]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key pgwiki2-mediawiki-:diff:1.41:old-1335:rev-1336:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>PavelStehule</name></author>
	</entry>
	<entry>
		<id>http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=1335&amp;oldid=prev</id>
		<title>PavelStehule v 22. 7. 2025, 16:05</title>
		<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=1335&amp;oldid=prev"/>
		<updated>2025-07-22T16:05:09Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;cs&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Starší verze&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Verze z 22. 7. 2025, 16:05&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l502&quot;&gt;Řádek 502:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Řádek 502:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;DPL&amp;gt;category=Verze PostgreSQL&amp;lt;/DPL&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;DPL&amp;gt;category=Verze PostgreSQL&amp;lt;/DPL&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Články]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Články]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Verze PostgreSQL]]&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>PavelStehule</name></author>
	</entry>
	<entry>
		<id>http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=614&amp;oldid=prev</id>
		<title>PavelStehule v 7. 6. 2021, 12:49</title>
		<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=614&amp;oldid=prev"/>
		<updated>2021-06-07T12:49:42Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;cs&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Starší verze&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Verze z 7. 6. 2021, 12:49&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l500&quot;&gt;Řádek 500:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Řádek 500:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;----------&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;----------&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Související články&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;Související články&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;ncl&lt;/del&gt;&amp;gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Category:&lt;/del&gt;Verze PostgreSQL&amp;lt;/&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;ncl&lt;/del&gt;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;DPL&lt;/ins&gt;&amp;gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;category=&lt;/ins&gt;Verze PostgreSQL&amp;lt;/&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;DPL&lt;/ins&gt;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Články]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Články]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Verze PostgreSQL]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Verze PostgreSQL]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key pgwiki2-mediawiki-:diff:1.41:old-514:rev-614:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>PavelStehule</name></author>
	</entry>
	<entry>
		<id>http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=514&amp;oldid=prev</id>
		<title>imported&gt;Pavel: /* Vlastní zpracování (příjem) dat v libpq (libpq row processor) */</title>
		<link rel="alternate" type="text/html" href="http://postgres.cz/index.php?title=PostgreSQL_9.2_(2012)&amp;diff=514&amp;oldid=prev"/>
		<updated>2012-08-28T04:10:02Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Vlastní zpracování (příjem) dat v libpq (libpq row processor)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Nová stránka&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Vývoj 9.2 pokračoval v kolejích vyjetých 9.0 a 9.1. Díky tomu, že v loni a předloni se vyřešily některé diskutabilní otázky (správa zdrojového kódu, název, vývojový cyklus), tak poslední rok byl hlavně a jen o práci. Ne, že by se občas nevedly bouřlivé diskuze. Ale téměř vždy se poměrně rychle podařilo najít rozumný kompromis - často i řešení, které bylo kvalitnější než původní návrhy. Poměrně razantních změn doznala architektura (nový proces pro CHECKPOINT). Víc než obvykle se měnil optimalizátor dotazů a změn nebyl ušetřen ani executor (zrychlení řazení o 20%). Některé koncepty, na kterých se pracovalo posledních několik let, dozrály a dostaly se do jádra (LEEKPROOF funkce, datový typ RANGE, datový typ JSON, podpora SP-GiST indexů). Třešničkou na dortu je funkcionalita, kterou uživatelé roky žádali - tzv index only scan. Konečně byl čas a prostor otestovat a připravit PostgreSQL pro o něco výkonnější hw než je zatím obvyklé. Pokud máte dost paměti na to, aby se Vám databáze vešla do paměti a více než 32 procesorů, pak byste měli zaregistrovat výrazné zrychlení. Dostalo se i na úspornost provozu - v případě, že PostgreSQL nebude zatížen, tak i servisní procesy budou v klidu (bez zbytečných periodických aktivit). &lt;br /&gt;
&lt;br /&gt;
=Změny v PL a SQL=&lt;br /&gt;
Funkce &amp;#039;&amp;#039;pg_trigger_depth()&amp;#039;&amp;#039; nám umožňuje včas kontrolovaně zastavit rekurzi triggeru. Přiznám se, že si nedovedu představit praktické použití této funkce vyjma debugování a řízeného vyhození výjimky (na internetu je možné dohledat několik příkladů - např. pro určení, zda-li by záznam modifikovaný z triggeru nebo z aplikace). Nově jsou k dispozici podmíněné příkazy ALTER - ALTER [TABLE|VIEW|SEQUENCE|INDEX) IF EXISTS, &lt;br /&gt;
&lt;br /&gt;
==GET STACKED DIAGNOSTICS v PL/pgSQL==&lt;br /&gt;
Na jednom projektu, na kterém jsem spolupracoval jsem potřeboval zachytit výjimku, zalogovat ji, a přeposlat dál. Což v PL/pgSQL bylo možné jen částečně, takže jsem narazil. V PL/pgSQL jsem neměl způsob, jak se dostat k jednotlivým položkám výjimky vyjma SQLERRM a SQLCODE. Po implementaci příkazu GET STACKED DIAGNOSTICS jsou veškerá data z výjimky (včetně kontextu) čitelná i z PL/pgSQL.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
create or replace function stacked_diagnostics_test() returns void as $$&lt;br /&gt;
declare _detail text;&lt;br /&gt;
        _hint text;&lt;br /&gt;
        _message text;&lt;br /&gt;
begin&lt;br /&gt;
  perform raise_test();&lt;br /&gt;
exception when others then&lt;br /&gt;
  get stacked diagnostics&lt;br /&gt;
        _message = message_text,&lt;br /&gt;
        _detail = pg_exception_detail,&lt;br /&gt;
        _hint = pg_exception_hint;&lt;br /&gt;
  raise notice &amp;#039;message: %, detail: %, hint: %&amp;#039;, _message, _detail, _hint;&lt;br /&gt;
end;&lt;br /&gt;
$$ language plpgsql;&lt;br /&gt;
select stacked_diagnostics_test();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Použití pojmenovaných parametrů v SQL==&lt;br /&gt;
Počínaje 9.2 padá omezení pro SQL funkce, kde nebylo možné používat pojmenované parametry - tj parametry funkce byly přistupné jen poziční notaci ($1, $2, $3). V 9.2 můžeme používat jména parametrů. Pozn. nekontrolují se kolize identifikátorů - vyšší prioritu mají SQL identifikátory. Parametr funkce je dostupný i pomocí notace název_funkce.název_parametru:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
create or replace function omega_b(a int) &lt;br /&gt;
returns int as $$ &lt;br /&gt;
select b from omega where a = omega_b.a &lt;br /&gt;
$$ language sql;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Notifikační trigger - Trigger Change Notification==&lt;br /&gt;
Návštěvníci posledních dvou P2D2 měli možnost se seznámit s mechanismem LISTEN/NOTIFY - jedná se o asynchronní notifikaci server/clients. Praktické použití tohoto mechanismu by měla zjednodušit funkce &amp;#039;&amp;#039;triggered_change_notification&amp;#039;&amp;#039; z modulu &amp;#039;&amp;#039;tcn&amp;#039;&amp;#039;. Tato funkce, pokud se použije jako obsluha triggeru rozesílá všem klientům přihlášeným k odběru zprávy &amp;#039;&amp;#039;tcn&amp;#039;&amp;#039; notifikaci o změně obsahu tabulky:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=# create extension tcn;&lt;br /&gt;
CREATE EXTENSION&lt;br /&gt;
postgres=# create table t1(id serial primary key, &lt;br /&gt;
                           a int, &lt;br /&gt;
                           b int);&lt;br /&gt;
NOTICE:  CREATE TABLE will create implicit sequence &amp;quot;t1_id_seq&amp;quot; for serial column &amp;quot;t1.id&amp;quot;&lt;br /&gt;
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index &amp;quot;t1_pkey&amp;quot; for table &amp;quot;t1&amp;quot;&lt;br /&gt;
CREATE TABLE&lt;br /&gt;
postgres=# create trigger t1_notify &lt;br /&gt;
              after insert or update or delete on tab &lt;br /&gt;
              for each row execute procedure triggered_change_notification();&lt;br /&gt;
CREATE TRIGGER&lt;br /&gt;
postgres=# listen tcn;&lt;br /&gt;
LISTEN&lt;br /&gt;
postgres=# insert into t1(a,b) values(10,20);&lt;br /&gt;
INSERT 0 1&lt;br /&gt;
Asynchronous notification &amp;quot;tcn&amp;quot; with payload &amp;quot;&amp;quot;t1&amp;quot;,I,&amp;quot;id&amp;quot;=&amp;#039;4&amp;#039;&amp;quot; received from server process with PID 10152.&lt;br /&gt;
postgres=# insert into t1(a,b) values(11,40);&lt;br /&gt;
INSERT 0 1&lt;br /&gt;
Asynchronous notification &amp;quot;tcn&amp;quot; with payload &amp;quot;&amp;quot;t1&amp;quot;,I,&amp;quot;id&amp;quot;=&amp;#039;5&amp;#039;&amp;quot; received from server process with PID 10152.&lt;br /&gt;
postgres=# delete from t1;&lt;br /&gt;
DELETE 2&lt;br /&gt;
Asynchronous notification &amp;quot;tcn&amp;quot; with payload &amp;quot;&amp;quot;t1&amp;quot;,D,&amp;quot;id&amp;quot;=&amp;#039;4&amp;#039;&amp;quot; received from server process with PID 10152.&lt;br /&gt;
Asynchronous notification &amp;quot;tcn&amp;quot; with payload &amp;quot;&amp;quot;t1&amp;quot;,D,&amp;quot;id&amp;quot;=&amp;#039;5&amp;#039;&amp;quot; received from server process with PID 10152.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==NOT VALID CHECK constraints==&lt;br /&gt;
Přidání omezující podmínky (constraint) do větší tabulky může být časově docela náročné, kontrolují se všechny záznamy v tabulce. V důsledku odpovídající příkaz ALTER TABLE bude trvat dlouho - a to může být na zatížené databázi docela problém (například kvůli zamykání - po dobu kontroly bude tabulka více-méně read only). Tento problém může být částečně vyřešen rozdělením operace do dvou kroků - přidáním nevalidní omezující podmínky. V3echny nově přidané záznamy pak musí splňovat nově přidanou, byť nevalidní podmínku - která může být validována dodatečně (při nižší zátěži). V další verzi by pak validace měla vyžadovat i méně agresivní zámky.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER TABLE test ADD CHECK ( field &amp;gt;= 0 ) NOT VALID;&lt;br /&gt;
ALTER TABLE test VALIDATE CONSTRAINT test_field_check;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Nové datové typy=&lt;br /&gt;
==Datové typy RANGE==&lt;br /&gt;
Počínaje 9.2 si vývojář může zaregistrovat vlastní datové typy třídy [http://www.postgresql.org/docs/devel/static/functions-range.html RANGE]. Hodnoty z třídy RANGE slouží k popisu nějakého rozsahu nebo intervalu. Hodí se například pro temporální databáze. Nejčastěji používané typy jsou již připravené:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=&amp;gt; \dT *range*&lt;br /&gt;
                       List of data types&lt;br /&gt;
   Schema   |   Name    |              Description              &lt;br /&gt;
------------+-----------+---------------------------------------&lt;br /&gt;
 pg_catalog | anyrange  | &lt;br /&gt;
 pg_catalog | daterange | range of dates&lt;br /&gt;
 pg_catalog | int4range | range of integers&lt;br /&gt;
 pg_catalog | int8range | range of bigints&lt;br /&gt;
 pg_catalog | numrange  | range of numerics&lt;br /&gt;
 pg_catalog | tsrange   | range of timestamps without time zone&lt;br /&gt;
 pg_catalog | tstzrange | range of timestamps with time zone&lt;br /&gt;
(7 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Název typu slouží jako i jako konstruktor hodnoty:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=&amp;gt; select daterange(current_date, current_date + 4);&lt;br /&gt;
        daterange        &lt;br /&gt;
-------------------------&lt;br /&gt;
 [2012-02-24,2012-02-28)&lt;br /&gt;
&lt;br /&gt;
postgres=&amp;gt; select numrange(10,30) n1, numrange &amp;#039;[10,20]&amp;#039; n2;&lt;br /&gt;
   n1    |   n2    &lt;br /&gt;
---------+---------&lt;br /&gt;
 [10,30) | [10,20]&lt;br /&gt;
(1 row)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
K dispozici je několik funkcí: empty, non_empty, lower (spodní limit), upper (horní limit), možnost zjištění překryvu, možnost určení průniku, test zda RANGE obsahuje hodnotu:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-- průnik&lt;br /&gt;
postgres=&amp;gt; select int4range(10, 20) * int4range(15, 25);&lt;br /&gt;
 ?column? &lt;br /&gt;
----------&lt;br /&gt;
 [15,20)&lt;br /&gt;
(1 row)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Původní motivací byla podpora temporálních databází - pomocí &amp;quot;exclusion constraints&amp;quot; můžeme jednoduše zajistit, že hodnoty typu RANGE budou disjunktivní (tj. nesmí dojít k překryvu rezervací):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
create table rezervace(trvani tsrange);&lt;br /&gt;
&lt;br /&gt;
alter table rezervace&lt;br /&gt;
  add exclude using gist (trvani WITH &amp;amp;&amp;amp;);&lt;br /&gt;
&lt;br /&gt;
insert into  rezervace values&lt;br /&gt;
  ( &amp;#039;[2010-01-01 11:30, 2010-01-01 13:00)&amp;#039; );&lt;br /&gt;
insert into  rezervace values&lt;br /&gt;
  ( &amp;#039;[2010-01-01 14:45, 2010-01-01 15:45)&amp;#039; );&lt;br /&gt;
&lt;br /&gt;
insert into  rezervace values&lt;br /&gt;
  ( &amp;#039;[2010-01-01 15:00, 2010-01-01 16:00)&amp;#039; );&lt;br /&gt;
ERROR:  conflicting key value violates exclusion constraint &amp;quot;rezervace_trvani_excl&amp;quot;&lt;br /&gt;
DETAIL:  Key (trvani)=([&amp;quot;2010-01-01 15:00:00&amp;quot;,&amp;quot;2010-01-01 16:00:00&amp;quot;)) conflicts with existing key (trvani)=([&amp;quot;2010-01-01 14:45:00&amp;quot;,&amp;quot;2010-01-01 15:45:00&amp;quot;)).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bez typů RANGE se k uložení používaly dvě nezávislé hodnoty - což v některých sutuacích vedlo k tomu, že se nepoužil index a bylo nutné převést data do multidimenzionálního prostoru a použít multidimenzionální indexy. S typy RANGE je takový postup minulostí.&lt;br /&gt;
&lt;br /&gt;
==JSON==&lt;br /&gt;
9.2 obsahuje podporu pro JSON. Je to hodně podobné podpoře XML. Dokument je uložen jako text (nicméně díky TOASTu může být zkomprimován) a databáze zajistí jeho validitu. Dále jsou k dispozici dvě funkce - &amp;#039;&amp;#039;array_to_json&amp;#039;&amp;#039; a &amp;#039;&amp;#039;row_to_json&amp;#039;&amp;#039;, které umožní vygenerovat dokument v JSONu. Podpora JSONu není v ANSI SQL, jako je XML a tudíž se využívají pouze generické mechanismy a nástroje PostgreSQL - nedošlo k úpravě parseru. SQL/XML poskytuje o hodně pohodlnější interface. Na druhou stranu, díky jednoduchosti JSONu není pro jeho sestavení a validaci potřeba žádná externí knihovna (jako je tomu u XML, kde je to celé postavené nad libXML2), a tudíž je vygenerování JSONu o hodně rychlejší než vygenerování XML:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=# create table f(a int, b boolean, c text, d date);&lt;br /&gt;
CREATE TABLE&lt;br /&gt;
postgres=# insert into f values(10,true, &amp;#039;Ahoj&amp;#039;, current_date),&lt;br /&gt;
                               (20, false,&amp;#039;Světe&amp;#039;, current_date+1);&lt;br /&gt;
INSERT 0 2&lt;br /&gt;
postgres=#  select array_to_json(array_agg(f), true) &lt;br /&gt;
               from f;&lt;br /&gt;
                  array_to_json                   &lt;br /&gt;
──────────────────────────────────────────────────&lt;br /&gt;
 [{&amp;quot;a&amp;quot;:10,&amp;quot;b&amp;quot;:true,&amp;quot;c&amp;quot;:&amp;quot;Ahoj&amp;quot;,&amp;quot;d&amp;quot;:&amp;quot;2012-02-25&amp;quot;}, ↵&lt;br /&gt;
  {&amp;quot;a&amp;quot;:20,&amp;quot;b&amp;quot;:null,&amp;quot;c&amp;quot;:&amp;quot;Světe&amp;quot;,&amp;quot;d&amp;quot;:&amp;quot;2012-02-26&amp;quot;}]&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
postgres=# select row_to_json(f) &lt;br /&gt;
              from f;&lt;br /&gt;
                  row_to_json                   &lt;br /&gt;
────────────────────────────────────────────────&lt;br /&gt;
 {&amp;quot;a&amp;quot;:10,&amp;quot;b&amp;quot;:true,&amp;quot;c&amp;quot;:&amp;quot;Ahoj&amp;quot;,&amp;quot;d&amp;quot;:&amp;quot;2012-02-25&amp;quot;}&lt;br /&gt;
 {&amp;quot;a&amp;quot;:20,&amp;quot;b&amp;quot;:null,&amp;quot;c&amp;quot;:&amp;quot;Světe&amp;quot;,&amp;quot;d&amp;quot;:&amp;quot;2012-02-26&amp;quot;}&lt;br /&gt;
(2 rows)&lt;br /&gt;
&lt;br /&gt;
-- pro projekci je nutné použít derivovanou tabulku&lt;br /&gt;
postgres=#  select array_to_json(array_agg(x), true) from (select a,b from f ) x;&lt;br /&gt;
    array_to_json    &lt;br /&gt;
─────────────────────&lt;br /&gt;
 [{&amp;quot;a&amp;quot;:10,&amp;quot;b&amp;quot;:true},↵&lt;br /&gt;
  {&amp;quot;a&amp;quot;:20,&amp;quot;b&amp;quot;:null}]&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
-- druhý parametr u funkcí je nepovinný&lt;br /&gt;
postgres=# select array_to_json(array_agg(row_to_json(f))) from f;&lt;br /&gt;
                                          array_to_json                                          &lt;br /&gt;
─────────────────────────────────────────────────────────────────────────────────────────────────&lt;br /&gt;
 [{&amp;quot;a&amp;quot;:10,&amp;quot;b&amp;quot;:true,&amp;quot;c&amp;quot;:&amp;quot;Ahoj&amp;quot;,&amp;quot;d&amp;quot;:&amp;quot;2012-02-25&amp;quot;},{&amp;quot;a&amp;quot;:20,&amp;quot;b&amp;quot;:false,&amp;quot;c&amp;quot;:&amp;quot;Světe&amp;quot;,&amp;quot;d&amp;quot;:&amp;quot;2012-02-26&amp;quot;}]&lt;br /&gt;
(1 row)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Bezpečnost=&lt;br /&gt;
==security bariers==&lt;br /&gt;
Pohledy lze v SQL databázi použít také k omezení přístupu k datům. Z důvodu implementace pohledů v PostgreSQL nezajišťují pohledy skutečně bezpečný přístup (pokud běžný uživatel může vytvářet funkce v PL/pgSQL - (viz leak views)). K prolomení ochrany potřebujeme funkci s minimální cenou, která zobrazí na ladící výstup hodnotu parametru:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
create or replace function public.fx(integer)&lt;br /&gt;
 returns boolean&lt;br /&gt;
 language plpgsql&lt;br /&gt;
 cost 1e-05&lt;br /&gt;
as $function$&lt;br /&gt;
begin&lt;br /&gt;
  raise notice &amp;#039;%&amp;#039;, $1;&lt;br /&gt;
  return true;&lt;br /&gt;
end;&lt;br /&gt;
$function$ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Vyrobím si tabulku omega, a pohled omega_view, přičemž pohled omega_view bude přístupný všem uživatelům a bude zobrazovat pouze liché řádky:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=# create table omega(a int);&lt;br /&gt;
CREATE TABLE&lt;br /&gt;
postgres=# create view omega_view as select a from omega where a % 2 = 1;&lt;br /&gt;
CREATE VIEW&lt;br /&gt;
postgres=# insert into omega values(1),(2),(3);&lt;br /&gt;
INSERT 0 3&lt;br /&gt;
postgres=# grant select on omega_view to public;&lt;br /&gt;
GRANT&lt;br /&gt;
postgres=# set role to tom;&lt;br /&gt;
SET&lt;br /&gt;
postgres=&amp;gt; select * from omega;&lt;br /&gt;
ERROR:  permission denied for relation omega&lt;br /&gt;
postgres=&amp;gt; select * from omega_view;&lt;br /&gt;
 a &lt;br /&gt;
───&lt;br /&gt;
 1&lt;br /&gt;
 3&lt;br /&gt;
(2 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nicméně, pokud Tom použije funkci fx, tak se dostane i k sudým řádkům (sice pouze skrz ladící výstup, ale i tak to může být problém):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=&amp;gt; select a from omega_view where fx(a);&lt;br /&gt;
NOTICE:  1&lt;br /&gt;
NOTICE:  2&lt;br /&gt;
NOTICE:  3&lt;br /&gt;
  ...&lt;br /&gt;
 a &lt;br /&gt;
───&lt;br /&gt;
 1&lt;br /&gt;
 3&lt;br /&gt;
(2 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Kde je zakopaný pes? Optimalizace díky flatteningu a nižší ceně upřednostní funkci fx() před operátorem modulo:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=&amp;gt; explain select a from omega_view where fx(a);&lt;br /&gt;
                      QUERY PLAN                      &lt;br /&gt;
──────────────────────────────────────────────────────&lt;br /&gt;
 Seq Scan on omega  (cost=0.00..46.00 rows=4 width=4)&lt;br /&gt;
   Filter: (fx(a) AND ((a % 2) = 1))&lt;br /&gt;
(2 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Výsledek je ok, ale zabezpečení bylo prolomeno. Donedávna byla dvě možní řešení - pohled nadefinovat s klauzulí OFFSET 0 (čímž se ale vyblokuje optimalizace) nebo běžnému uživateli odepřít možnost definovat vlastní funkce:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-- utocnik neuvidi nepatricna data, ale take nedojde k pouziti pripadneho indexu&lt;br /&gt;
postgres=&amp;gt; explain select a from omega_view where fx(a) and a between 1 and 10;&lt;br /&gt;
                                  QUERY PLAN                                   &lt;br /&gt;
───────────────────────────────────────────────────────────────────────────────&lt;br /&gt;
 Subquery Scan on omega_view  (cost=0.00..190.80 rows=1 width=4)&lt;br /&gt;
   Filter: (fx(omega_view.a) AND (omega_view.a &amp;gt;= 1) AND (omega_view.a &amp;lt;= 10))&lt;br /&gt;
   -&amp;gt;  Limit  (cost=0.00..190.04 rows=50 width=4)&lt;br /&gt;
         -&amp;gt;  Seq Scan on omega  (cost=0.00..190.04 rows=50 width=4)&lt;br /&gt;
               Filter: ((a % 2) = 1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
V 9.2 se tento bezpečnostní nebo výkonnostní problém řeší systémově - zavádí se tzv bezpečnostní bariéry, které blokují některé potenciálně rizikové optimalizace:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
create view omega_view with (security_barrier=true) as select a from omega where a % 2 = 1;&lt;br /&gt;
postgres=# set role to tom;&lt;br /&gt;
SET&lt;br /&gt;
postgres=&amp;gt; select a from omega_view where fx(a) and a between 1 and 10;&lt;br /&gt;
NOTICE:  1&lt;br /&gt;
NOTICE:  3&lt;br /&gt;
NOTICE:  5&lt;br /&gt;
NOTICE:  7&lt;br /&gt;
NOTICE:  9&lt;br /&gt;
 a &lt;br /&gt;
───&lt;br /&gt;
 1&lt;br /&gt;
 3&lt;br /&gt;
 5&lt;br /&gt;
 7&lt;br /&gt;
 9&lt;br /&gt;
(5 rows)&lt;br /&gt;
&lt;br /&gt;
postgres=&amp;gt; explain select a from omega_view where fx(a) and a between 1 and 10;&lt;br /&gt;
                                     QUERY PLAN                                     &lt;br /&gt;
────────────────────────────────────────────────────────────────────────────────────&lt;br /&gt;
 Subquery Scan on omega_view  (cost=0.00..8.49 rows=1 width=4)&lt;br /&gt;
   Filter: fx(omega_view.a)&lt;br /&gt;
   -&amp;gt;  Index Only Scan using omega_a_idx on omega  (cost=0.00..8.48 rows=1 width=4)&lt;br /&gt;
         Index Cond: ((a &amp;gt;= 1) AND (a &amp;lt;= 10))&lt;br /&gt;
         Filter: ((a % 2) = 1)&lt;br /&gt;
(5 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Takže pokud plánujete použít pohled pro omezení přístupu k datům, nezapomeňte pohled označit atributem &amp;#039;&amp;#039;security_barier&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=Výkon=&lt;br /&gt;
Jako obvykle došlo k úpravám planneru (optimalizace). Optimalizátor v 9.2 by si měl o něco lépe poradit s dotazy, kde optimální plán vyžaduje zanořený nested-loop. Robert Haas (a nejen on) věnoval hromadu času odstranění některých interních zámků, což by se mělo projevit na platformách, kde je dostatek paměti (databáze se vejde beze zbytku do paměti) a dostatek CPU (obvykle 32 CPU a více). Minimálně v ČR vím o jedné instalaci PostgreSQL, kde by rozhodně měli 9.2 z tohoto důvodu vyzkoušet. Docela zásadně se optimalizovala implementace ORDER BY. V případě, že je možné provést seřazení pouze v paměti, tak můžete očekávat 20-30% zrychlení.&lt;br /&gt;
&lt;br /&gt;
Také implementace příkazu COPY doznala změn - v komentáři k patchi je poznámka, že urychlení by se mělo týkat hlavně úzkých dlouhých tabulek a paralelního načítání. Z jednoduchého syntetického testu (obnova dvou cca 250MB tabulek) mi vychází trochu něco jiného - zhruba 20% zrychlení v jednom vlákně (z 76 sec na 60 sec) a zhruba 2.5% zpomalení (z 40 na 41 sec)  v importu ve dvou vláknech (výsledky berte hodně orientačně - test byl velice jednoduchý a provedený na notebooku (starší DELL 830), nikoliv odpovídajícím železe). &lt;br /&gt;
&lt;br /&gt;
Chování příkazu COMMIT lze ovlivnit nastavením proměnné &amp;#039;&amp;#039;synchronous_commit&amp;#039;&amp;#039;. Tato proměnná ovlivňuje, co všechno se musí stát, než DB &amp;quot;prohlásí&amp;quot; příkaz COMMIT za provedený. Výchozí nastavení ON je maximálně bezpečné. Naopak nastavení OFF bezpečné není - v případě pádu můžeme přijít o transakce, přestože databáze potvrdila klientu jejich úspěšné ukončení (nicméně i v případě ztráty posledních transakcí nedojde k porušení konzistence databáze). V 9.2 můžeme použít pro nastavení této proměnné hodnoty &amp;quot;remote_write&amp;quot; a &amp;quot;local&amp;quot;. &amp;quot;remote_write&amp;quot; má smysl pro synchronní replikaci - způsobí, že pro dokončení COMMITu na masteru stačí zápis do transakčního logu repliky aniž by se čekalo na fsync (vynucený zápis cache). Při této úrovni můžete přijít o transakce pouze v případě, že dojde zároveň k havárii primárního serveru a repliky. O něco vyšší úroveň &amp;quot;local&amp;quot; vynutí čekání na dokončení fsyncu na primárním serveru (bez čekání na fsync repliky). A když už jsem nakousl replikaci - v 9.2 nechybí podpora pro víceúrovňovou replikaci - master/slave/slave - tj. replikovat lze i repliku.&lt;br /&gt;
&lt;br /&gt;
==SP-GiST==&lt;br /&gt;
Teodor Sigaev and a Bartunov napsali podporu pro další třídu indexů: SP-GiST. Nad touto třídou indexů lze vybudovat quad-trees, k-d trees, suffix trees indexy, které pro vybrané spektrum úloh jsou vhodnější než GiST a to ať dobou přístupu, tak dobou vytváření indexu. Jedná se o horkou novinku - význam se ukáže během několika dalších let (až dojde k integraci v PostGISu - komunita kolem PostGISu sponzorovala vývoj). V prezentacích se demonstruje až 3-5 násobné zrychlení vůči GiSTu. Jelikož nemám k dispozici vhodná data, tak předávám, jak jsem dostal.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
--&lt;br /&gt;
-- SP-GiST&lt;br /&gt;
--&lt;br /&gt;
CREATE TABLE quad_point_tbl AS&lt;br /&gt;
    SELECT point(unique1,unique2) AS p FROM tenk1;&lt;br /&gt;
INSERT INTO quad_point_tbl&lt;br /&gt;
    SELECT &amp;#039;(333.0,400.0)&amp;#039;::point FROM generate_series(1,1000);&lt;br /&gt;
CREATE INDEX sp_quad_ind ON quad_point_tbl USING spgist (p);&lt;br /&gt;
CREATE TABLE kd_point_tbl AS SELECT * FROM quad_point_tbl;&lt;br /&gt;
CREATE INDEX sp_kd_ind ON kd_point_tbl USING spgist (p kd_point_ops);&lt;br /&gt;
CREATE TABLE suffix_text_tbl AS&lt;br /&gt;
    SELECT name AS t FROM road;&lt;br /&gt;
INSERT INTO suffix_text_tbl&lt;br /&gt;
    SELECT &amp;#039;0123456789abcdef&amp;#039; FROM generate_series(1,1000);&lt;br /&gt;
INSERT INTO suffix_text_tbl VALUES (&amp;#039;0123456789abcde&amp;#039;);&lt;br /&gt;
INSERT INTO suffix_text_tbl VALUES (&amp;#039;0123456789abcdefF&amp;#039;);&lt;br /&gt;
CREATE INDEX sp_suff_ind ON suffix_text_tbl USING spgist (t);&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
==Index only scan==&lt;br /&gt;
Jednou z nevýhod multigenerační architektury (minimálně její implementace v PostgreSQL) byla nutnost každý záznam vybraný pomocí indexu ověřit na zdrojové tabulce (a i tehdy, když index obsahoval všechna požadovaná data). Tento nedostatek se nyní podařilo vyřešit - díky implementaci tzv visibility maps (primárně byly implementovány pro optimalizaci provádění příkazu VACUUM). Podpora metody index only scan může relativně razantně zrychlit některé dotazy typu SELECT agg(x) FROM tab WHERE x = konstanta:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=# \dt+&lt;br /&gt;
                    List of relations&lt;br /&gt;
 Schema | Name  | Type  |  Owner   |  Size  | Description &lt;br /&gt;
--------+-------+-------+----------+--------+-------------&lt;br /&gt;
 public | omega | table | postgres | 349 MB | &lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
postgres=# select count(*) from omega;&lt;br /&gt;
  count   &lt;br /&gt;
----------&lt;br /&gt;
 10100000&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
postgres=# vacuum analyze omega;&lt;br /&gt;
VACUUM&lt;br /&gt;
Time: 897.607 ms&lt;br /&gt;
&lt;br /&gt;
postgres=# select count(*) from omega where a between 1 and 500;&lt;br /&gt;
 count  &lt;br /&gt;
--------&lt;br /&gt;
 504350&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
Time: 1312.926 ms&lt;br /&gt;
&lt;br /&gt;
postgres=# create index on omega(a);&lt;br /&gt;
CREATE INDEX&lt;br /&gt;
Time: 17334.431 ms&lt;br /&gt;
&lt;br /&gt;
postgres=# select count(*) from omega where a between 1 and 500;&lt;br /&gt;
 count  &lt;br /&gt;
--------&lt;br /&gt;
 504350&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
Time: 77.910 ms&lt;br /&gt;
&lt;br /&gt;
postgres=# select sum(b) from omega where a between 501 and 1000;&lt;br /&gt;
    sum     &lt;br /&gt;
------------&lt;br /&gt;
 2512689175&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
Time: 1216.973 ms&lt;br /&gt;
&lt;br /&gt;
postgres=# create index on omega(a,b);&lt;br /&gt;
CREATE INDEX&lt;br /&gt;
Time: 19097.679 ms&lt;br /&gt;
&lt;br /&gt;
postgres=# select sum(b) from omega where a between 501 and 1000;&lt;br /&gt;
    sum     &lt;br /&gt;
------------&lt;br /&gt;
 2512689175&lt;br /&gt;
(1 row)&lt;br /&gt;
&lt;br /&gt;
Time: 88.614 ms&lt;br /&gt;
&lt;br /&gt;
postgres=# explain select sum(b) from omega where a between 501 and 1000;&lt;br /&gt;
                                          QUERY PLAN                                           &lt;br /&gt;
-----------------------------------------------------------------------------------------------&lt;br /&gt;
 Aggregate  (cost=17134.85..17134.86 rows=1 width=4)&lt;br /&gt;
   -&amp;gt;  Index Only Scan using omega_a_b_idx on omega  (cost=0.00..15855.79 rows=511623 width=4)&lt;br /&gt;
         Index Cond: ((a &amp;gt;= 501) AND (a &amp;lt;= 1000))&lt;br /&gt;
(3 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Pozor - aby se mohl použít index only scan, je nutné tabulku nejdříve &amp;quot;zvakuovat&amp;quot;&amp;#039;&amp;#039;.VACUUM aktualizuje případně vytvoří mapu viditelnosti (visibility map), a pokud ta pro tabulku neexistuje, pak není možné použít index only scan .&lt;br /&gt;
&lt;br /&gt;
==Prepared statements==&lt;br /&gt;
&lt;br /&gt;
Předpřipravené dotazy (prepared statements) jsou užitečnou pomůckou v boji s SQL injection. V předchozích verzích ovšem trpěly nepěkným neduhem – dotaz byl optimalizován „na slepo“ pro nejpravděpodobnější hodnoty parametrů. V některých případech se prováděcí plán připraveného dotazu mohl znatelně lišit od optimálního prováděcího plánu – a bylo nutné použít dynamické SQL (častěji se s tím setkávají vývojáři v PL/pgSQL). V 9.2 se s vlastní optimalizací dotazu počká až na zpracování dotazu, kdy jsou známé parametry dotazu a pro ně se dohledá optimální prováděcí plán. V případech, kdy je pravděpodobné, že generický plán bude podobný plánu generovaného se znalostí parametrů, se použije generický plán.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=# prepare xx(int) as select * from gg where a = $1;&lt;br /&gt;
PREPARE&lt;br /&gt;
postgres=# explain execute xx(1);&lt;br /&gt;
                       QUERY PLAN&lt;br /&gt;
---------------------------------------------------------&lt;br /&gt;
 Seq Scan on gg  (cost=0.00..1694.25 rows=99973 width=4)&lt;br /&gt;
   Filter: (a = 1)&lt;br /&gt;
(2 rows)&lt;br /&gt;
&lt;br /&gt;
postgres=# explain execute xx(0);&lt;br /&gt;
                                QUERY PLAN&lt;br /&gt;
---------------------------------------------------------------------------&lt;br /&gt;
 Index Only Scan using gg_a_idx on gg  (cost=0.00..17.30 rows=127 width=4)&lt;br /&gt;
   Index Cond: (a = 0)&lt;br /&gt;
(2 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=API=&lt;br /&gt;
==Vlastní zpracování (příjem) dat v libpq (libpq row processor)==&lt;br /&gt;
&amp;#039;&amp;#039;libpq&amp;#039;&amp;#039; je knihovna zajišťující komunikaci mezi databází a klientem. Při zpracování dotazu se průběžně odesílají data (řádky) ze serveru na klienta, kde se v libpq ukládají do paměti (pole). Po úspěšném dokončení dotazu vrátí libpq klientské aplikaci ukazatel na pole s výsledkem dotazu. Tento režim je jednoduchý a praktický, vyjma případů, kdy se na klienta posílají gigabajty dat (takže klient vyžírá paměť) a nebo kdy chceme přijatá data zpracovávat průběžně. V předchozích verzích bylo jediné (a správné) řešení použití kurzorů (příkazy DECLARE CURSOR a FETCH), které umožňují postupné zpracování dotazu. Občas se ale kurzor nehodí - třeba proto, že nechcete měnit logiku klienta - a pak se může hodit možnost změnit způsob příjmu řádků v libpq (např. - &amp;quot;online&amp;quot; plnění db gridu). Nyní je libpq hook &amp;#039;&amp;#039;PQrowProcessor&amp;#039;&amp;#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
typedef struct pgDataValue&lt;br /&gt;
{&lt;br /&gt;
    int         len;            /* data length in bytes, or &amp;lt;0 if NULL */&lt;br /&gt;
    const char *value;          /* data value, without zero-termination */&lt;br /&gt;
} PGdataValue;&lt;br /&gt;
&lt;br /&gt;
typedef int (*PQrowProcessor) (PGresult *res, const PGdataValue *columns,&lt;br /&gt;
                               const char **errmsgp, void *param);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Prvním uživatelem tohoto hooku je modul &amp;#039;&amp;#039;dblink&amp;#039;&amp;#039;, kde se výsledek přesměrovává do objektu typu &amp;#039;&amp;#039;tuple store&amp;#039;&amp;#039; místo do pole jako dříve. &amp;#039;&amp;#039;Tuple store&amp;#039;&amp;#039; &amp;quot;inteligentně&amp;quot; ukládá data do paměti nebo do souboru v případě, že velikost ukládaných dat přesáhne &amp;#039;&amp;#039;work_mem&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
====Poznámka====&lt;br /&gt;
Toto API se ještě během finalizece změnilo - původně bylo založené na callbacku - nyní stávající funkce umí vracet jeden řádek.&lt;br /&gt;
&lt;br /&gt;
=UI=&lt;br /&gt;
Tentokrát žádné razantní změny nečekejte - spíš jenom maličkosti, jako je třeba autocomplete v psql, který zachovává velikosti písmen i u klíčových slov, nebo automatické formátování definic pohledů. Funkce &amp;#039;&amp;#039;pg_cancel_backend&amp;#039;&amp;#039; může použít i &amp;quot;obyčejný&amp;quot; uživatel na své dotazy. V minulých verzích tato funkce vyžadovala právo superuser.&lt;br /&gt;
&lt;br /&gt;
S podporou víceúrovňové replikace (kaskádové replikace) souvisí i možnost použít &amp;#039;&amp;#039;pg_basebackup&amp;#039;&amp;#039; (fyzická online záloha) vůči replice. &amp;#039;&amp;#039;pg_dump&amp;#039;&amp;#039; poskytoval možnost, jak vyexportovat vybrané tabulky. Nyní s parametrem &amp;#039;&amp;#039;--exclude-table&amp;#039;&amp;#039; umožňuje nezálohovat vybrané tabulky (typicky logy). Konzole &amp;#039;&amp;#039;psql&amp;#039;&amp;#039; 9.2 podporuje metapříkaz \ir, kde je relativní cesta vztažena k importovanému souboru (a nikoliv k aktuálnímu pracovnímu souboru). &lt;br /&gt;
&lt;br /&gt;
Cízí zdroje se dočkaly podpory statistik - příkaz ANALYZE lze pustit i nad externí tabulkou. Akurátní statistiky by se měly projevit v optimalizaci prováděcího plánu dotazu.&lt;br /&gt;
&lt;br /&gt;
==Automatické formátování definic pohledů==&lt;br /&gt;
Potěšilo mne, že Andrew Dunstan [http://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=2f582f76b1945929ff07116cd4639747ce9bb8a1 použil] můj oblíbený způsob zápisu, který navrhl [http://en.wikipedia.org/wiki/Joe_Celko Joe Celko].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=# create table f1(a int);&lt;br /&gt;
CREATE TABLE&lt;br /&gt;
postgres=# create table f2(a int);&lt;br /&gt;
CREATE TABLE&lt;br /&gt;
postgres=# create view v1 as select f1.a as a, f2.a as b from f1,f2 where f1.a = f2.a;&lt;br /&gt;
CREATE VIEW&lt;br /&gt;
&lt;br /&gt;
postgres=# \d+ v1&lt;br /&gt;
                   View &amp;quot;public.v1&amp;quot;&lt;br /&gt;
 Column │  Type   │ Modifiers │ Storage │ Description &lt;br /&gt;
────────┼─────────┼───────────┼─────────┼─────────────&lt;br /&gt;
 a      │ integer │           │ plain   │ &lt;br /&gt;
 b      │ integer │           │ plain   │ &lt;br /&gt;
View definition:&lt;br /&gt;
 SELECT f1.a, f2.a AS b&lt;br /&gt;
   FROM f1, f2&lt;br /&gt;
  WHERE f1.a = f2.a;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Změny v pg_stat_*==&lt;br /&gt;
Na výkon serveru má vliv i skutečnost, jestli máme nebo nemáme možnost identifikovat (nebo alespoň detekovat) situace, které vedou k nižšímu výkonu. Na celkovém výkonu aplikace se podepíší kromě jiného deadlocky a použití dočasných souborů. Výskyt deadlocků nebo použití tmp souborů bylo možné vyčíst už dříve - z logů. V 9.1 byly přidány do pohledu pg_stat_database sloupce obsahující celkový počet deadlocků a celkovou velikost zapsaných dočasných souborů:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=&amp;gt; select datname, temp_files, temp_bytes, deadlocks, stats_reset from pg_stat_database;&lt;br /&gt;
  datname  | temp_files | temp_bytes | deadlocks |          stats_reset          &lt;br /&gt;
-----------+------------+------------+-----------+-------------------------------&lt;br /&gt;
 template1 |          0 |          0 |         0 | &lt;br /&gt;
 template0 |          0 |          0 |         0 | &lt;br /&gt;
 postgres  |         10 | 1267789120 |         0 | 2012-02-23 07:24:10.488168+01&lt;br /&gt;
(3 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Znáte [http://pgfouine.projects.postgresql.org/ pgFouine]? Pokud ne, tak se na něj určitě podívejte - je to SQL profiler. Hodně zjednodušenou variantu (modul &amp;#039;&amp;#039;pg_stat_statements&amp;#039;&amp;#039;) objevíte i v Postgresu. Nově tento modul umí normalizovat dotazy. Normalizací se, v tomto případě, myslí nahrazení konstant parametrem:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
postgres=# select * from pg_proc where proname = &amp;#039;sin&amp;#039;;&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
postgres=# select * from pg_stat_statements where query like &amp;#039;%pg_proc%&amp;#039;;&lt;br /&gt;
─[ RECORD 1 ]───────┬─────────────────────────────────────────&lt;br /&gt;
userid              │ 16384&lt;br /&gt;
dbid                │ 12870&lt;br /&gt;
query               │ select * from pg_proc where proname = ?;&lt;br /&gt;
calls               │ 4&lt;br /&gt;
total_time          │ 0.000743&lt;br /&gt;
rows                │ 4&lt;br /&gt;
shared_blks_hit     │ 10&lt;br /&gt;
shared_blks_read    │ 2&lt;br /&gt;
shared_blks_dirtied │ 0&lt;br /&gt;
shared_blks_written │ 0&lt;br /&gt;
local_blks_hit      │ 0&lt;br /&gt;
local_blks_read     │ 0&lt;br /&gt;
local_blks_dirtied  │ 0&lt;br /&gt;
local_blks_written  │ 0&lt;br /&gt;
temp_blks_read      │ 0&lt;br /&gt;
temp_blks_written   │ 0&lt;br /&gt;
time_read           │ 0&lt;br /&gt;
time_write          │ 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Modul se zavádí skrze změnu konfigurace Postgresu:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shared_preload_libraries = &amp;#039;pg_stat_statements&amp;#039;     # (change requires restart)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Závěr, a co se letos nestihlo=&lt;br /&gt;
Intenzivně se pracuje a diskutuje nad možností CRC součtů datových stránek. Ještě pár týdnů potřebuje patch implementující DDL triggery. Já jsem si od loňského léta hrál s možností důkladnější kontroly funkcí v plpgsql. Aktuálně už se asi vyjasnila požadovaná funkcionalita, pro kterou existuje [http://archives.postgresql.org/pgsql-hackers/2012-03/gzPauv4ZB_87.gz patch] a teď se hledá způsob, jak minimalizovat duplicitní kód v PL/pgSQL (pokud píšete v PL/pgSQL tak mohu jedině doporučit opatchovat si PL/pgSQL):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
select plpgsql_check_function(&amp;#039;f1()&amp;#039;, fatal_errors := false);&lt;br /&gt;
                         plpgsql_check_function                         &lt;br /&gt;
------------------------------------------------------------------------&lt;br /&gt;
 error:42703:4:SQL statement:column &amp;quot;c&amp;quot; of relation &amp;quot;t1&amp;quot; does not exist&lt;br /&gt;
 Query: update t1 set c = 30&lt;br /&gt;
 --                   ^&lt;br /&gt;
 error:42P01:7:RAISE:missing FROM-clause entry for table &amp;quot;r&amp;quot;&lt;br /&gt;
 Query: SELECT r.c&lt;br /&gt;
 --            ^&lt;br /&gt;
 error:42601:7:RAISE:too few parameters specified for RAISE&lt;br /&gt;
(7 rows)&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
Dost času se věnovalo minimalizaci zamykání vynuceného implementací referenční integrity. Bohužel navržené řešení způsobovalo cca 10% propad výkonu, takže se do Postgresu letos nedostalo - ale docela bych si vsadil, že příští rok už se do jádra dostane. Zajímavou možností bude podpora indexů pro regulární výrazy.&lt;br /&gt;
&lt;br /&gt;
Myslím si, že 9.2ou se částečně uzavírá dost hektická etapa vývoje PostgreSQL, kdy se nestíhalo dostatečně rychle aplikovat patche do jádra. Během této etapy bylo vždy více patchů než se stihlo aplikovat během jednoho cyklu. Každý rok se do vývoje zapojilo více vývojářů a každý rok nová verze obsahovala více nové funkcionality než verze předchozí. Nemyslím si, že bude dále pokračovat v takovém tempu a předpokládám, že vývoj trochu zvolní. V příštím roce  se  více prostoru dostane různým extenzím PostgreSQL a postupnému vylepšování optimalizátoru, tam kde dnes občas selhává (prepared statements, sledování korelace mezi sloupci) . V dalších letech pravděpodobně dojde k integraci projektu Postgres-XC - tj podpoře multi master replikace a nativního HA řešení.Co bude dál - kdo ví - nyní je PostgreSQL  výborná OLTP databáze - ukazuje se, že by uživatelé rádi používali PostgreSQL i jako analytickou databázi. PostgreSQL zatím na analytiku nad archivními daty optimalizovaný není, to by se ale mohlo výhledově (5 let) změnit.&lt;br /&gt;
----------&lt;br /&gt;
Související články&lt;br /&gt;
&amp;lt;ncl&amp;gt;Category:Verze PostgreSQL&amp;lt;/ncl&amp;gt;&lt;br /&gt;
[[Category:Články]]&lt;br /&gt;
[[Category:Verze PostgreSQL]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Pavel</name></author>
	</entry>
</feed>