[Trad] [svn:pgfr] r1355 - in traduc/tags: . tv840rc2

admin at listes.postgresql.fr admin at listes.postgresql.fr
Sam 27 Juin 12:41:55 CEST 2009


Author: gleu
Date: 2009-06-27 12:41:54 +0200 (Sat, 27 Jun 2009)
New Revision: 1355

Added:
   traduc/tags/tv840rc2/
   traduc/tags/tv840rc2/gist.xml
   traduc/tags/tv840rc2/storage.xml
Removed:
   traduc/tags/tv840rc2/gist.xml
   traduc/tags/tv840rc2/storage.xml
Log:
Ajout du tag de la 8.4 RC2.



Property changes on: traduc/tags/tv840rc2
___________________________________________________________________
Added: svn:mergeinfo
   + 

Deleted: traduc/tags/tv840rc2/gist.xml
===================================================================
--- traduc/trunk/postgresql/gist.xml	2009-06-23 22:14:31 UTC (rev 1352)
+++ traduc/tags/tv840rc2/gist.xml	2009-06-27 10:41:54 UTC (rev 1355)
@@ -1,687 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-15"?>
-<!-- Dernière modification
-     le       $Date$
-     par      $Author$
-     révision $Revision$ -->
-
-<chapter id="gist">
-<title>Index GiST</title>
-
-   <indexterm>
-    <primary>index</primary>
-    <secondary>GiST</secondary>
-   </indexterm>
-
-<sect1 id="gist-intro">
- <title>Introduction</title>
-
- <para>
-   <acronym>GiST</acronym> est un acronyme de <foreignphrase>Generalized
-   Search Tree</foreignphrase>, c'est-à-dire arbre de recherche généralisé.
-   C'est une méthode d'accès balancée à structure de type arbre,
-   qui agit comme un modèle de base dans lequel il est possible d'implanter
-   des schémas d'indexage arbitraires. B-trees, R-trees et de nombreux autres
-   schémas d'indexage peuvent être implantés en <acronym>GiST</acronym>.
- </para>
-
- <para>
-  <acronym>GiST</acronym> a pour avantage d'autoriser le développement
-  de types de données personnalisés avec les méthodes d'accès appropriées, par
-  un expert en types de données, plutôt que par un expert en
-  bases de données.
- </para>
-
-  <para>
-   Quelques informations disponibles ici sont dérivées du <ulink
-   url="http://gist.cs.berkeley.edu/">site web</ulink> du projet d'indexage
-   GiST de l'université de Californie à Berkeley et de la <ulink
-    url="http://www.sai.msu.su/~megera/postgres/gist/papers/concurrency/access-methods-for-next-generation.pdf.gz">thèse
-   de Marcel Kornacker, 
-   Méthodes d'accès pour les systèmes de bases de données de la prochaine
-   génération</ulink>. L'implantation <acronym>GiST</acronym> de
-   <productname>PostgreSQL</productname> est principalement maintenu
-   par Teodor Sigaev et Oleg Bartunov. Leur <ulink
-   url="http://www.sai.msu.su/~megera/postgres/gist/">site web</ulink> fournit
-   de plus amples informations.
-  </para>
-
-</sect1>
-
-<sect1 id="gist-extensibility">
- <title>Extensibilité</title>
-
- <para>
-  L'implantation d'une nouvelle méthode d'accès à un index
-  a toujours été un travail complexe. Il est, en effet, nécessaire de comprendre le
-  fonctionnement interne de la base de données, tel que le gestionnaire de
-  verrous ou le WAL.
- </para>
- <para>
-  L'interface <acronym>GiST</acronym> dispose d'un haut niveau
-  d'abstraction, ce qui autorise le codeur de la méthode d'accès à
-  ne coder que la sémantique du type de données accédé. La
-  couche <acronym>GiST</acronym> se charge elle-même de la gestion des accès concurrents,
-  des traces et de la recherche dans la structure en arbre.
- </para>
- 
- <para>
-   Cette extensibilité n'est pas comparable à celle des
-   autres arbres de recherche standard en termes de données gérées. Par
-   exemple, <productname>PostgreSQL</productname> supporte les B-trees et les
-   index de hachage extensibles. Cela signifie qu'il est possible d'utiliser
-   <productname>PostgreSQL</productname> pour construire un B-tree ou un hachage
-   sur tout type de données. Mais, les B-trees ne supportent
-   que les prédicats d'échelle (<literal>&lt;</literal>,
-   <literal>=</literal>, <literal>&gt;</literal>), les index de hachage
-   que les requêtes d'égalité.
- </para>
- 
- <para>
-   Donc, lors de l'indexation d'une collection d'images, par exemple, avec un B-tree
-   <productname>PostgreSQL</productname>, seules peuvent être lancées des requêtes de type  
-   <quote>est-ce que imagex est égale à imagey</quote>,
-   <quote>est-ce que imagex est plus petite que imagey</quote> et <quote>est-ce
-   que imagex est plus grande que imagey</quote>. En fonction de la définition
-   donnée à <quote>égale à</quote>, <quote>inférieure à</quote> ou
-   <quote>supérieure à</quote>, cela peut avoir une utilité.
-   Néanmoins, l'utilisation d'un index basé sur <acronym>GiST</acronym> permet
-   de créer de nombreuses possibilités de poser des questions spécifiques au domaine,
-   telles que <quote>trouver toutes les images de chevaux</quote> ou
-   <quote>trouver toutes les images sur-exposées</quote>.
- </para>
-
- <para>
-   Pour obtenir une méthode d'accès
-   <acronym>GiST</acronym> fonctionnelle, il suffit de coder sept méthodes
-   utilisateur définissant le comportement des clés dans
-   l'arbre. Ces méthodes doivent être suffisamment élaborées
-   pour supporter des requêtes avancées, mais pour toutes les requêtes standard
-   (B-trees, R-trees, etc.) elles sont relativement simples. En bref,
-   <acronym>GiST</acronym> combine extensibilité, généralité, 
-   ré-utilisation de code et interface claire.
-  </para>
-
-</sect1>
-
-<sect1 id="gist-implementation">
- <title>Implantation</title>
- 
- <para>
-   Une classe d'opérateur d'index <acronym>GiST</acronym> doit fournir sept
-   méthodes. Correctness of the index is ensured
-   by proper implementation of the <function>same</function>, <function>consistent</function>
-   and <function>union</function> methods, while efficiency (size and speed) of the
-   index will depend on the <function>penalty</function> and <function>picksplit</function>
-   methods.
-   The remaining two methods are <function>compress</function> and
-   <function>decompress</function>, which allow an index to have internal tree data of
-   a different type than the data it indexes. The leaves are to be of the
-   indexed data type, while the other tree nodes can be of any C struct (but
-   you still have to follow <productname>PostgreSQL</productname> datatype rules here,
-   see about <literal>varlena</literal> for variable sized data). If the tree's
-   internal data type exists at the SQL level, the <literal>STORAGE</literal> option
-   of the <command>CREATE OPERATOR CLASS</command> command can be used.
-
- </para>
-
- <variablelist>
-    <varlistentry>
-     <term><function>consistent</function></term>
-     <listitem>
-      <para>
-       Given an index entry <literal>p</literal> and a query value <literal>q</literal>,
-       this function determines whether the index entry is
-       <quote>consistent</quote> with the query; that is, could the predicate
-       <quote><replaceable>indexed_column</replaceable>
-       <replaceable>indexable_operator</replaceable> <literal>q</literal></quote> be true for
-       any row represented by the index entry?  For a leaf index entry this is
-       equivalent to testing the indexable condition, while for an internal
-       tree node this determines whether it is necessary to scan the subtree
-       of the index represented by the tree node.  When the result is
-       <literal>true</literal>, a <literal>recheck</literal> flag must also be returned.
-       This indicates whether the predicate is certainly true or only possibly
-       true.  If <literal>recheck</literal> = <literal>false</literal> then the index has
-       tested the predicate condition exactly, whereas if <literal>recheck</literal>
-       = <literal>true</literal> the row is only a candidate match.  In that case the
-       system will automatically evaluate the
-       <replaceable>indexable_operator</replaceable> against the actual row value to see
-       if it is really a match.  This convention allows
-       <acronym>GiST</acronym> to support both lossless and lossy index
-       structures.
-      </para>
-
-      <para>
-        The <acronym>SQL</acronym> declaration of the function must look like this:
-
-<programlisting>
-CREATE OR REPLACE FUNCTION my_consistent(internal, data_type, smallint, oid, internal)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-</programlisting>
-
-        And the matching code in the C module could then follow this skeleton:
-
-<programlisting>
-Datum       my_consistent(PG_FUNCTION_ARGS);
-PG_FUNCTION_INFO_V1(my_consistent);
-
-Datum
-my_consistent(PG_FUNCTION_ARGS)
-{
-    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
-    data_type  *query = PG_GETARG_DATA_TYPE_P(1);
-    StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
-    /* Oid subtype = PG_GETARG_OID(3); */
-    bool       *recheck = (bool *) PG_GETARG_POINTER(4);
-    data_type  *key = DatumGetDataType(entry-&gt;key);
-    bool        retval;
-
-    /*
-     * determine return value as a function of strategy, key and query.
-     *
-     * Use GIST_LEAF(entry) to know where you're called in the index tree,
-     * which comes handy when supporting the = operator for example (you could
-     * check for non empty union() in non-leaf nodes and equality in leaf
-     * nodes).
-     */
-
-    *recheck = true;        /* or false if check is exact */
-
-    PG_RETURN_BOOL(retval);
-}
-</programlisting>
-
-       Here, <varname>key</varname> is an element in the index and <varname>query</varname>
-       the value being looked up in the index. The <literal>StrategyNumber</literal>
-       parameter indicates which operator of your operator class is being
-       applied &mdash; it matches one of the operator numbers in the
-       <command>CREATE OPERATOR CLASS</command> command.  Depending on what operators
-       you have included in the class, the data type of <varname>query</varname> could
-       vary with the operator, but the above skeleton assumes it doesn't.
-      </para>
-
-     </listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><function>union</function></term>
-     <listitem>
-      <para>
-       This method consolidates information in the tree.  Given a set of
-       entries, this function generates a new index entry that represents
-       all the given entries.
-      </para>
-
-      <para>
-        The <acronym>SQL</acronym> declaration of the function must look like this:
-
-<programlisting>
-CREATE OR REPLACE FUNCTION my_union(internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-</programlisting>
-
-        And the matching code in the C module could then follow this skeleton:
-
-<programlisting>
-Datum       my_union(PG_FUNCTION_ARGS);
-PG_FUNCTION_INFO_V1(my_union);
-
-Datum
-my_union(PG_FUNCTION_ARGS)
-{
-    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-    GISTENTRY  *ent = entryvec-&gt;vector;
-    data_type  *out,
-               *tmp,
-               *old;
-    int         numranges,
-                i = 0;
-
-    numranges = entryvec-&gt;n;
-    tmp = DatumGetDataType(ent[0].key);
-    out = tmp;
-
-    if (numranges == 1)
-    {
-        out = data_type_deep_copy(tmp);
-
-        PG_RETURN_DATA_TYPE_P(out);
-    }
-
-    for (i = 1; i &lt; numranges; i++)
-    {
-        old = out;
-        tmp = DatumGetDataType(ent[i].key);
-        out = my_union_implementation(out, tmp);
-    }
-
-    PG_RETURN_DATA_TYPE_P(out);
-}
-</programlisting>
-      </para>
-
-      <para>
-        As you can see, in this skeleton we're dealing with a data type
-        where <literal>union(X, Y, Z) = union(union(X, Y), Z)</literal>. It's easy
-        enough to support data types where this is not the case, by
-        implementing the proper union algorithm in this
-        <acronym>GiST</acronym> support method.
-      </para>
-
-      <para>
-        The <function>union</function> implementation function should return a
-        pointer to newly <function>palloc()</function>ed memory. You can't just
-        return whatever the input is.
-      </para>
-     </listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><function>compress</function></term>
-     <listitem>
-      <para>
-       Convertit l'élément de données dans un format compatible avec
-       le stockage physique dans une page d'index.
-      </para>
-
-      <para>
-        The <acronym>SQL</acronym> declaration of the function must look like this:
-
-<programlisting>
-CREATE OR REPLACE FUNCTION my_compress(internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-</programlisting>
-
-        And the matching code in the C module could then follow this skeleton:
-
-<programlisting>
-Datum       my_compress(PG_FUNCTION_ARGS);
-PG_FUNCTION_INFO_V1(my_compress);
-
-Datum
-my_compress(PG_FUNCTION_ARGS)
-{
-    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
-    GISTENTRY  *retval;
-
-    if (entry-&gt;leafkey)
-    {
-        /* replace entry-&gt;key with a compressed version */
-        compressed_data_type *compressed_data = palloc(sizeof(compressed_data_type));
-
-        /* fill *compressed_data from entry-&gt;key ... */
-
-        retval = palloc(sizeof(GISTENTRY));
-        gistentryinit(*retval, PointerGetDatum(compressed_data),
-                      entry-&gt;rel, entry-&gt;page, entry-&gt;offset, FALSE);
-    }
-    else
-    {
-        /* typically we needn't do anything with non-leaf entries */
-        retval = entry;
-    }
-
-    PG_RETURN_POINTER(retval);
-}
-</programlisting>
-      </para>
-
-      <para>
-       You have to adapt <replaceable>compressed_data_type</replaceable> to the specific
-       type you're converting to in order to compress your leaf nodes, of
-       course.
-      </para>
-
-      <para>
-        Depending on your needs, you could also need to care about
-        compressing <literal>NULL</literal> values in there, storing for example
-        <literal>(Datum) 0</literal> like <literal>gist_circle_compress</literal> does.
-      </para>
-     </listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><function>decompress</function></term>
-     <listitem>
-      <para>
-       L'inverse de la fonction <function>compress</function>. Convertit la
-       représentation de l'élément de donnée en un format manipulable par la base
-       de données.
-      </para>
-
-      <para>
-        The <acronym>SQL</acronym> declaration of the function must look like this:
-
-<programlisting>
-CREATE OR REPLACE FUNCTION my_decompress(internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-</programlisting>
-
-        And the matching code in the C module could then follow this skeleton:
-
-<programlisting>
-Datum       my_decompress(PG_FUNCTION_ARGS);
-PG_FUNCTION_INFO_V1(my_decompress);
-
-Datum
-my_decompress(PG_FUNCTION_ARGS)
-{
-    PG_RETURN_POINTER(PG_GETARG_POINTER(0));
-}
-</programlisting>
-
-        The above skeleton is suitable for the case where no decompression
-        is needed.
-      </para>
-     </listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><function>penalty</function></term>
-     <listitem>
-      <para>
-       Renvoie une valeur indiquant le <quote>coût</quote> d'insertion
-       d'une nouvelle entrée dans une branche particulière de l'arbre. Les
-       éléments seront insérés dans l'ordre des pénalités moindres
-       (<function>penalty</function>) de l'arbre.
-      </para>
-
-      <para>
-        The <acronym>SQL</acronym> declaration of the function must look like this:
-
-<programlisting>
-CREATE OR REPLACE FUNCTION my_penalty(internal, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;  -- in some cases penalty functions need not be strict
-</programlisting>
-
-        And the matching code in the C module could then follow this skeleton:
-
-<programlisting>
-Datum       my_penalty(PG_FUNCTION_ARGS);
-PG_FUNCTION_INFO_V1(my_penalty);
-
-Datum
-my_penalty(PG_FUNCTION_ARGS)
-{
-    GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
-    GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
-    float      *penalty = (float *) PG_GETARG_POINTER(2);
-    data_type  *orig = DatumGetDataType(origentry-&gt;key);
-    data_type  *new = DatumGetDataType(newentry-&gt;key);
-
-    *penalty = my_penalty_implementation(orig, new);
-    PG_RETURN_POINTER(penalty);
-}
-</programlisting>
-      </para>
-
-      <para>
-        The <function>penalty</function> function is crucial to good performance of
-        the index. It'll get used at insertion time to determine which branch
-        to follow when choosing where to add the new entry in the tree. At
-        query time, the more balanced the index, the quicker the lookup.
-      </para>
-     </listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><function>picksplit</function></term>
-     <listitem>
-      <para>
-       When an index page split is necessary, this function decides which
-       entries on the page are to stay on the old page, and which are to move
-       to the new page.
-      </para>
-
-      <para>
-        The <acronym>SQL</acronym> declaration of the function must look like this:
-
-<programlisting>
-CREATE OR REPLACE FUNCTION my_picksplit(internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-</programlisting>
-
-        And the matching code in the C module could then follow this skeleton:
-
-<programlisting>
-Datum       my_picksplit(PG_FUNCTION_ARGS);
-PG_FUNCTION_INFO_V1(my_picksplit);
-
-Datum
-my_picksplit(PG_FUNCTION_ARGS)
-{
-    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
-    OffsetNumber maxoff = entryvec-&gt;n - 1;
-    GISTENTRY  *ent = entryvec-&gt;vector;
-    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
-    int         i,
-                nbytes;
-    OffsetNumber *left,
-               *right;
-    data_type  *tmp_union;
-    data_type  *unionL;
-    data_type  *unionR;
-    GISTENTRY **raw_entryvec;
-
-    maxoff = entryvec-&gt;n - 1;
-    nbytes = (maxoff + 1) * sizeof(OffsetNumber);
-
-    v-&gt;spl_left = (OffsetNumber *) palloc(nbytes);
-    left = v-&gt;spl_left;
-    v-&gt;spl_nleft = 0;
-
-    v-&gt;spl_right = (OffsetNumber *) palloc(nbytes);
-    right = v-&gt;spl_right;
-    v-&gt;spl_nright = 0;
-
-    unionL = NULL;
-    unionR = NULL;
-
-    /* Initialize the raw entry vector. */
-    raw_entryvec = (GISTENTRY **) malloc(entryvec-&gt;n * sizeof(void *));
-    for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
-        raw_entryvec[i] = &amp;(entryvec-&gt;vector[i]);
-
-    for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
-    {
-        int         real_index = raw_entryvec[i] - entryvec-&gt;vector;
-
-        tmp_union = DatumGetDataType(entryvec-&gt;vector[real_index].key);
-        Assert(tmp_union != NULL);
-
-        /*
-         * Choose where to put the index entries and update unionL and unionR
-         * accordingly. Append the entries to either v_spl_left or
-         * v_spl_right, and care about the counters.
-         */
-
-        if (my_choice_is_left(unionL, curl, unionR, curr))
-        {
-            if (unionL == NULL)
-                unionL = tmp_union;
-            else
-                unionL = my_union_implementation(unionL, tmp_union);
-
-            *left = real_index;
-            ++left;
-            ++(v-&gt;spl_nleft);
-        }
-        else
-        {
-            /*
-             * Same on the right
-             */
-        }
-    }
-
-    v-&gt;spl_ldatum = DataTypeGetDatum(unionL);
-    v-&gt;spl_rdatum = DataTypeGetDatum(unionR);
-    PG_RETURN_POINTER(v);
-}
-</programlisting>
-      </para>
-
-      <para>
-        Like <function>penalty</function>, the <function>picksplit</function> function
-        is crucial to good performance of the index.  Designing suitable
-        <function>penalty</function> and <function>picksplit</function> implementations
-        is where the challenge of implementing well-performing
-        <acronym>GiST</acronym> indexes lies.
-      </para>
-     </listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><function>same</function></term>
-     <listitem>
-      <para>
-       Returns true if two index entries are identical, false otherwise.
-      </para>
-
-      <para>
-        The <acronym>SQL</acronym> declaration of the function must look like this:
-
-<programlisting>
-CREATE OR REPLACE FUNCTION my_same(internal, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT;
-</programlisting>
-
-        And the matching code in the C module could then follow this skeleton:
-
-<programlisting>
-Datum       my_same(PG_FUNCTION_ARGS);
-PG_FUNCTION_INFO_V1(my_same);
-
-Datum
-my_same(PG_FUNCTION_ARGS)
-{
-    prefix_range *v1 = PG_GETARG_PREFIX_RANGE_P(0);
-    prefix_range *v2 = PG_GETARG_PREFIX_RANGE_P(1);
-    bool       *result = (bool *) PG_GETARG_POINTER(2);
-
-    *result = my_eq(v1, v2);
-    PG_RETURN_POINTER(result);
-}
-</programlisting>
-
-        For historical reasons, the <function>same</function> function doesn't
-        just return a boolean result; instead it has to store the flag
-        at the location indicated by the third argument.
-      </para>
-     </listitem>
-    </varlistentry>
-
-  </variablelist>
-
-</sect1>
-
-<sect1 id="gist-examples">
- <title>Exemples</title>
-
- <para>
-  La distribution source de <productname>PostgreSQL</productname> inclut
-  plusieurs exemples de méthodes d'indexation implantées selon
-  <acronym>GiST</acronym>. Le système principal fournit des fonctionnalités
-  de recherche plein texte (indexation des <type>tsvector</type> et
-  <type>tsquery</type>) ainsi que des fonctionnalités équivalentes aux R-Tree
-  pour certains types de données géométriques
-  (voir <filename>src/backend/access/gist/gistproc.c</filename>). Les modules
-  <filename>contrib</filename> suivants contiennent aussi des classes d'opérateur
-  <acronym>GiST</acronym>&nbsp;:
- </para>
- 
- <variablelist>
-  <varlistentry>
-   <term>btree_gist</term>
-   <listitem>
-    <para>Fonctionnalités équivalentes aux B-Tree pour plusieurs types de
-    données</para>
-   </listitem>
-  </varlistentry>
-
-  <varlistentry>
-   <term>cube</term>
-   <listitem>
-    <para>Indexation de cubes multi-dimensionnels</para>
-   </listitem>
-  </varlistentry>
-
-  <varlistentry>
-   <term>hstore</term>
-   <listitem>
-    <para>Module pour le stockage des paires (clé, valeur)</para>
-   </listitem>
-  </varlistentry>
-
-  <varlistentry>
-   <term>intarray</term>
-   <listitem>
-    <para>RD-Tree pour tableaux uni-dimensionnels de valeurs int4</para>
-   </listitem>
-  </varlistentry>
-
-  <varlistentry>
-   <term>ltree</term>
-   <listitem>
-    <para>Indexation des structures de type arbre</para>
-   </listitem>
-  </varlistentry>
-
-  <varlistentry>
-   <term>pg_trgm</term>
-   <listitem>
-    <para>Similarité textuelle par correspondance de trigrammes</para>
-   </listitem>
-  </varlistentry>
-
-  <varlistentry>
-   <term>seg</term>
-   <listitem>
-    <para>Indexation pour les <quote>nombres
-     flottants</quote></para>
-   </listitem>
-  </varlistentry>
- </variablelist>
-
-</sect1>
-
-<sect1 id="gist-recovery">
- <title>Récupération après un arrêt brutal</title>
-
- <para>
-  Il est généralement suffisant de rejouer les traces WAL pour restaurer l'intégrité d'un
-  index GiST après un arrêt brutal de la base de données. Néanmoins, il existe
-  quelques cas particuliers pour lesquels l'état de l'index n'est pas
-  entièrement reconstruit. L'index reste fonctionnellement correct mais
-  les performances peuvent se trouver dégradées. Lorsque cela
-  arrive, l'index peut être réparé par <command>VACUUM</command> de sa table, ou
-  par reconstruction avec <command>REINDEX</command>. Dans certains cas, un simple
-  <command>VACUUM</command> ne suffit pas et un <command>VACUUM FULL</command>
-  ou un <command>REINDEX</command> est nécessaire. Ce besoin est indiqué par
-  la survenue d'un tel message&nbsp;:
-<programlisting>LOG:  index NNN/NNN/NNN needs VACUUM or REINDEX to finish crash recovery
-</programlisting>
-  ou le message suivant lors d'insertions dans l'index&nbsp;:
-<programlisting>LOG:  index "FOO" needs VACUUM or REINDEX to finish crash recovery
-</programlisting>
-  Si un simple <command>VACUUM</command> est incapable de réaliser
-  complètement la récupération, l'avertissement suivant est envoyé&nbsp;:
-<programlisting>NOTICE:  index "FOO" needs VACUUM FULL or REINDEX to finish crash recovery
-</programlisting>
- </para>
-</sect1>
-
-</chapter>

Copied: traduc/tags/tv840rc2/gist.xml (from rev 1353, traduc/trunk/postgresql/gist.xml)
===================================================================
--- traduc/tags/tv840rc2/gist.xml	                        (rev 0)
+++ traduc/tags/tv840rc2/gist.xml	2009-06-27 10:41:54 UTC (rev 1355)
@@ -0,0 +1,704 @@
+<?xml version="1.0" encoding="ISO-8859-15"?>
+<!-- Dernière modification
+     le       $Date$
+     par      $Author$
+     révision $Revision$ -->
+
+<chapter id="gist">
+<title>Index GiST</title>
+
+   <indexterm>
+    <primary>index</primary>
+    <secondary>GiST</secondary>
+   </indexterm>
+
+<sect1 id="gist-intro">
+ <title>Introduction</title>
+
+ <para>
+   <acronym>GiST</acronym> est un acronyme de <foreignphrase>Generalized
+   Search Tree</foreignphrase>, c'est-à-dire arbre de recherche généralisé.
+   C'est une méthode d'accès balancée à structure de type arbre,
+   qui agit comme un modèle de base dans lequel il est possible d'implanter
+   des schémas d'indexage arbitraires. B-trees, R-trees et de nombreux autres
+   schémas d'indexage peuvent être implantés en <acronym>GiST</acronym>.
+ </para>
+
+ <para>
+  <acronym>GiST</acronym> a pour avantage d'autoriser le développement
+  de types de données personnalisés avec les méthodes d'accès appropriées, par
+  un expert en types de données, plutôt que par un expert en
+  bases de données.
+ </para>
+
+  <para>
+   Quelques informations disponibles ici sont dérivées du <ulink
+   url="http://gist.cs.berkeley.edu/">site web</ulink> du projet d'indexage
+   GiST de l'université de Californie à Berkeley et de la <ulink
+    url="http://www.sai.msu.su/~megera/postgres/gist/papers/concurrency/access-methods-for-next-generation.pdf.gz">thèse
+   de Marcel Kornacker, 
+   Méthodes d'accès pour les systèmes de bases de données de la prochaine
+   génération</ulink>. L'implantation <acronym>GiST</acronym> de
+   <productname>PostgreSQL</productname> est principalement maintenu
+   par Teodor Sigaev et Oleg Bartunov. Leur <ulink
+   url="http://www.sai.msu.su/~megera/postgres/gist/">site web</ulink> fournit
+   de plus amples informations.
+  </para>
+
+</sect1>
+
+<sect1 id="gist-extensibility">
+ <title>Extensibilité</title>
+
+ <para>
+  L'implantation d'une nouvelle méthode d'accès à un index
+  a toujours été un travail complexe. Il est, en effet, nécessaire de comprendre le
+  fonctionnement interne de la base de données, tel que le gestionnaire de
+  verrous ou le WAL.
+ </para>
+ 
+ <para>
+  L'interface <acronym>GiST</acronym> dispose d'un haut niveau
+  d'abstraction, ce qui autorise le codeur de la méthode d'accès à
+  ne coder que la sémantique du type de données accédé. La
+  couche <acronym>GiST</acronym> se charge elle-même de la gestion des accès concurrents,
+  des traces et de la recherche dans la structure en arbre.
+ </para>
+ 
+ <para>
+   Cette extensibilité n'est pas comparable à celle des
+   autres arbres de recherche standard en termes de données gérées. Par
+   exemple, <productname>PostgreSQL</productname> supporte les B-trees et les
+   index de hachage extensibles. Cela signifie qu'il est possible d'utiliser
+   <productname>PostgreSQL</productname> pour construire un B-tree ou un hachage
+   sur tout type de données. Mais, les B-trees ne supportent
+   que les prédicats d'échelle (<literal>&lt;</literal>,
+   <literal>=</literal>, <literal>&gt;</literal>), les index de hachage
+   que les requêtes d'égalité.
+ </para>
+ 
+ <para>
+   Donc, lors de l'indexation d'une collection d'images, par exemple, avec un B-tree
+   <productname>PostgreSQL</productname>, seules peuvent être lancées des requêtes de type  
+   <quote>est-ce que imagex est égale à imagey</quote>,
+   <quote>est-ce que imagex est plus petite que imagey</quote> et <quote>est-ce
+   que imagex est plus grande que imagey</quote>. En fonction de la définition
+   donnée à <quote>égale à</quote>, <quote>inférieure à</quote> ou
+   <quote>supérieure à</quote>, cela peut avoir une utilité.
+   Néanmoins, l'utilisation d'un index basé sur <acronym>GiST</acronym> permet
+   de créer de nombreuses possibilités de poser des questions spécifiques au domaine,
+   telles que <quote>trouver toutes les images de chevaux</quote> ou
+   <quote>trouver toutes les images sur-exposées</quote>.
+ </para>
+
+ <para>
+   Pour obtenir une méthode d'accès
+   <acronym>GiST</acronym> fonctionnelle, il suffit de coder sept méthodes
+   utilisateur définissant le comportement des clés dans
+   l'arbre. Ces méthodes doivent être suffisamment élaborées
+   pour supporter des requêtes avancées, mais pour toutes les requêtes standard
+   (B-trees, R-trees, etc.) elles sont relativement simples. En bref,
+   <acronym>GiST</acronym> combine extensibilité, généralité, 
+   ré-utilisation de code et interface claire.
+  </para>
+
+</sect1>
+
+<sect1 id="gist-implementation">
+ <title>Implantation</title>
+ 
+ <para>
+   Une classe d'opérateur d'index <acronym>GiST</acronym> doit fournir sept
+   méthodes. Correctness of the index is ensured
+   by proper implementation of the <function>same</function>, <function>consistent</function>
+   and <function>union</function> methods, while efficiency (size and speed) of the
+   index will depend on the <function>penalty</function> and <function>picksplit</function>
+   methods.
+   The remaining two methods are <function>compress</function> and
+   <function>decompress</function>, which allow an index to have internal tree data of
+   a different type than the data it indexes. The leaves are to be of the
+   indexed data type, while the other tree nodes can be of any C struct (but
+   you still have to follow <productname>PostgreSQL</productname> datatype rules here,
+   see about <literal>varlena</literal> for variable sized data). If the tree's
+   internal data type exists at the SQL level, the <literal>STORAGE</literal> option
+   of the <command>CREATE OPERATOR CLASS</command> command can be used.
+ </para>
+
+ <variablelist>
+    <varlistentry>
+     <term><function>consistent</function></term>
+     <listitem>
+      <para>
+       Given an index entry <literal>p</literal> and a query value <literal>q</literal>,
+       this function determines whether the index entry is
+       <quote>consistent</quote> with the query; that is, could the predicate
+       <quote><replaceable>indexed_column</replaceable>
+       <replaceable>indexable_operator</replaceable> <literal>q</literal></quote> be true for
+       any row represented by the index entry?  For a leaf index entry this is
+       equivalent to testing the indexable condition, while for an internal
+       tree node this determines whether it is necessary to scan the subtree
+       of the index represented by the tree node.  When the result is
+       <literal>true</literal>, a <literal>recheck</literal> flag must also be returned.
+       This indicates whether the predicate is certainly true or only possibly
+       true.  If <literal>recheck</literal> = <literal>false</literal> then the index has
+       tested the predicate condition exactly, whereas if <literal>recheck</literal>
+       = <literal>true</literal> the row is only a candidate match.  In that case the
+       system will automatically evaluate the
+       <replaceable>indexable_operator</replaceable> against the actual row value to see
+       if it is really a match.  This convention allows
+       <acronym>GiST</acronym> to support both lossless and lossy index
+       structures.
+      </para>
+
+      <para>
+        La déclaration <acronym>SQL</acronym> de la fonction doit ressembler à
+	ceci&nbsp;:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_consistent(internal, data_type, smallint, oid, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+
+        Et le code correspondant dans le module C peut alors suivre ce
+	squelette&nbsp;:
+
+<programlisting>
+Datum       my_consistent(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(my_consistent);
+
+Datum
+my_consistent(PG_FUNCTION_ARGS)
+{
+    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+    data_type  *query = PG_GETARG_DATA_TYPE_P(1);
+    StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+    /* Oid subtype = PG_GETARG_OID(3); */
+    bool       *recheck = (bool *) PG_GETARG_POINTER(4);
+    data_type  *key = DatumGetDataType(entry-&gt;key);
+    bool        retval;
+
+    /*
+     * determine return value as a function of strategy, key and query.
+     *
+     * Use GIST_LEAF(entry) to know where you're called in the index tree,
+     * which comes handy when supporting the = operator for example (you could
+     * check for non empty union() in non-leaf nodes and equality in leaf
+     * nodes).
+     */
+
+    *recheck = true;        /* or false if check is exact */
+
+    PG_RETURN_BOOL(retval);
+}
+</programlisting>
+
+       Ici, <varname>key</varname> est un élément dans l'index et
+       <varname>query</varname> la valeur la recherchée dans l'index. Le
+       paramètre <literal>StrategyNumber</literal> indique l'opérateur
+       appliqué de votre classe d'opérateur. Il correspond à un des nombres
+       d'opérateurs dans la commande <command>CREATE OPERATOR CLASS</command>.
+       Suivant les opérateurs que vous avez inclus dans la classe, le type de
+       données de <varname>query</varname> pourrait varier avec l'opérateur,
+       mais le squelette ci-dessus suppose que ce n'est pas le cas.
+      </para>
+
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><function>union</function></term>
+     <listitem>
+      <para>
+       Cette méthode consolide l'information dans l'arbre. Suivant un ensemble
+       d'entrées, cette fonction génère une nouvelle entrée d'index qui
+       représente toutes les entrées données.
+      </para>
+
+      <para>
+        La déclaration <acronym>SQL</acronym> de la fonction doit ressembler à
+	ceci&nbsp;:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_union(internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+
+        Et le code correspondant dans le module C peut alors suivre ce
+	squelette&nbsp;:
+
+<programlisting>
+Datum       my_union(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(my_union);
+
+Datum
+my_union(PG_FUNCTION_ARGS)
+{
+    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+    GISTENTRY  *ent = entryvec-&gt;vector;
+    data_type  *out,
+               *tmp,
+               *old;
+    int         numranges,
+                i = 0;
+
+    numranges = entryvec-&gt;n;
+    tmp = DatumGetDataType(ent[0].key);
+    out = tmp;
+
+    if (numranges == 1)
+    {
+        out = data_type_deep_copy(tmp);
+
+        PG_RETURN_DATA_TYPE_P(out);
+    }
+
+    for (i = 1; i &lt; numranges; i++)
+    {
+        old = out;
+        tmp = DatumGetDataType(ent[i].key);
+        out = my_union_implementation(out, tmp);
+    }
+
+    PG_RETURN_DATA_TYPE_P(out);
+}
+</programlisting>
+      </para>
+
+      <para>
+        Comme vous pouvez le voir dans ce quelette, nous gérons un type de
+	données où <literal>union(X, Y, Z) = union(union(X, Y), Z)</literal>.
+	C'est assez simple pour supporter les types de données où ce n'est pas
+	le cas, en implantant un autre algorithme d'union dans cette méthode
+	de support <acronym>GiST</acronym>.
+      </para>
+
+      <para>
+        La fonction d'implantation de <function>union</function> doit renvoyer
+	un pointeur vers la mémoire qui vient d'être allouée via la fonction
+        <function>palloc()</function>. Vous ne pouvez pas tout simplement
+	renvoyer l'entrée.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><function>compress</function></term>
+     <listitem>
+      <para>
+       Convertit l'élément de données dans un format compatible avec
+       le stockage physique dans une page d'index.
+      </para>
+
+      <para>
+        La déclaration <acronym>SQL</acronym> de la fonction doit ressembler à
+	ceci&nbsp;:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_compress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+
+        Et le code correspondant dans le module C peut alors suivre ce
+	squelette&nbsp;:
+
+<programlisting>
+Datum       my_compress(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(my_compress);
+
+Datum
+my_compress(PG_FUNCTION_ARGS)
+{
+    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+    GISTENTRY  *retval;
+
+    if (entry-&gt;leafkey)
+    {
+        /* replace entry-&gt;key with a compressed version */
+        compressed_data_type *compressed_data = palloc(sizeof(compressed_data_type));
+
+        /* fill *compressed_data from entry-&gt;key ... */
+
+        retval = palloc(sizeof(GISTENTRY));
+        gistentryinit(*retval, PointerGetDatum(compressed_data),
+                      entry-&gt;rel, entry-&gt;page, entry-&gt;offset, FALSE);
+    }
+    else
+    {
+        /* typically we needn't do anything with non-leaf entries */
+        retval = entry;
+    }
+
+    PG_RETURN_POINTER(retval);
+}
+</programlisting>
+      </para>
+
+      <para>
+       Vous devez adapter <replaceable>compressed_data_type</replaceable> au type
+       spécifique que vous essayez d'obtenir pour compresser les n&oelig;uds
+       finaux.
+      </para>
+
+      <para>
+        Vous pourriez aussi avoir besoin de faire attention à la compression des
+	valeurs <literal>NULL</literal>, en enregistrant par exemple
+        <literal>(Datum) 0</literal> comme le fait <literal>gist_circle_compress</literal>.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><function>decompress</function></term>
+     <listitem>
+      <para>
+       L'inverse de la fonction <function>compress</function>. Convertit la
+       représentation de l'élément de donnée en un format manipulable par la base
+       de données.
+      </para>
+
+      <para>
+        La déclaration <acronym>SQL</acronym> de la fonction doit ressembler à
+	ceci&nbsp;:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_decompress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+
+        Et le code correspondant dans le module C peut alors suivre ce
+	squelette&nbsp;:
+
+<programlisting>
+Datum       my_decompress(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(my_decompress);
+
+Datum
+my_decompress(PG_FUNCTION_ARGS)
+{
+    PG_RETURN_POINTER(PG_GETARG_POINTER(0));
+}
+</programlisting>
+
+        Le squelette ci-dessus est convenable dans le cas iù aucune
+	décompression n'est nécessaire.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><function>penalty</function></term>
+     <listitem>
+      <para>
+       Renvoie une valeur indiquant le <quote>coût</quote> d'insertion
+       d'une nouvelle entrée dans une branche particulière de l'arbre. Les
+       éléments seront insérés dans l'ordre des pénalités moindres
+       (<function>penalty</function>) de l'arbre.
+      </para>
+
+      <para>
+        La déclaration <acronym>SQL</acronym> de la fonction doit ressembler à
+	ceci&nbsp;:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_penalty(internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;  -- in some cases penalty functions need not be strict
+</programlisting>
+
+        Et le code correspondant dans le module C peut alors suivre ce
+	squelette&nbsp;:
+
+<programlisting>
+Datum       my_penalty(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(my_penalty);
+
+Datum
+my_penalty(PG_FUNCTION_ARGS)
+{
+    GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
+    GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
+    float      *penalty = (float *) PG_GETARG_POINTER(2);
+    data_type  *orig = DatumGetDataType(origentry-&gt;key);
+    data_type  *new = DatumGetDataType(newentry-&gt;key);
+
+    *penalty = my_penalty_implementation(orig, new);
+    PG_RETURN_POINTER(penalty);
+}
+</programlisting>
+      </para>
+
+      <para>
+        La fonction <function>penalty</function> est crucial pour de bonnes
+	performances de l'index. Elle sera utilisée lors de l'insertion pour
+	déterminer la branche à suivre pour savoir où ajoter la nouvelle entrée
+	dans l'arbre. Lors de l'exécution de la requête, plus l'arbre sera bien
+	balancé, plus l'exécution sera rapide.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><function>picksplit</function></term>
+     <listitem>
+      <para>
+       Quand une division de page est nécessaire pour un index, cette fonction
+       décide des entrées de la page qui resteront sur l'ancienne page et de
+       celles qui seront déplacées sur la nouvelle page.
+      </para>
+
+      <para>
+        La déclaration <acronym>SQL</acronym> de la fonction doit ressembler à
+	ceci&nbsp;:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_picksplit(internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+
+        Et le code correspondant dans le module C peut alors suivre ce
+	squelette&nbsp;:
+
+<programlisting>
+Datum       my_picksplit(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(my_picksplit);
+
+Datum
+my_picksplit(PG_FUNCTION_ARGS)
+{
+    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+    OffsetNumber maxoff = entryvec-&gt;n - 1;
+    GISTENTRY  *ent = entryvec-&gt;vector;
+    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+    int         i,
+                nbytes;
+    OffsetNumber *left,
+               *right;
+    data_type  *tmp_union;
+    data_type  *unionL;
+    data_type  *unionR;
+    GISTENTRY **raw_entryvec;
+
+    maxoff = entryvec-&gt;n - 1;
+    nbytes = (maxoff + 1) * sizeof(OffsetNumber);
+
+    v-&gt;spl_left = (OffsetNumber *) palloc(nbytes);
+    left = v-&gt;spl_left;
+    v-&gt;spl_nleft = 0;
+
+    v-&gt;spl_right = (OffsetNumber *) palloc(nbytes);
+    right = v-&gt;spl_right;
+    v-&gt;spl_nright = 0;
+
+    unionL = NULL;
+    unionR = NULL;
+
+    /* Initialize the raw entry vector. */
+    raw_entryvec = (GISTENTRY **) malloc(entryvec-&gt;n * sizeof(void *));
+    for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
+        raw_entryvec[i] = &amp;(entryvec-&gt;vector[i]);
+
+    for (i = FirstOffsetNumber; i &lt;= maxoff; i = OffsetNumberNext(i))
+    {
+        int         real_index = raw_entryvec[i] - entryvec-&gt;vector;
+
+        tmp_union = DatumGetDataType(entryvec-&gt;vector[real_index].key);
+        Assert(tmp_union != NULL);
+
+        /*
+         * Choose where to put the index entries and update unionL and unionR
+         * accordingly. Append the entries to either v_spl_left or
+         * v_spl_right, and care about the counters.
+         */
+
+        if (my_choice_is_left(unionL, curl, unionR, curr))
+        {
+            if (unionL == NULL)
+                unionL = tmp_union;
+            else
+                unionL = my_union_implementation(unionL, tmp_union);
+
+            *left = real_index;
+            ++left;
+            ++(v-&gt;spl_nleft);
+        }
+        else
+        {
+            /*
+             * Same on the right
+             */
+        }
+    }
+
+    v-&gt;spl_ldatum = DataTypeGetDatum(unionL);
+    v-&gt;spl_rdatum = DataTypeGetDatum(unionR);
+    PG_RETURN_POINTER(v);
+}
+</programlisting>
+      </para>
+
+      <para>
+        Comme <function>penalty</function>, la fonction <function>picksplit</function>
+	est cruciale pour de bonnes performances de l'index. Concevoir des
+	implantations convenables des fonctions <function>penalty</function> et
+	<function>picksplit</function> est le challenge d'un index
+        <acronym>GiST</acronym> performant.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><function>same</function></term>
+     <listitem>
+      <para>
+       Renvoit true si les deux entrées de l'index sont identiques, faux sinon.
+      </para>
+
+      <para>
+        La déclaration <acronym>SQL</acronym> de la fonction ressemble à
+	ceci&nbsp;:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_same(internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+
+        Et le code correspondant dans le module C peut alors suivre ce
+	squelette&nbsp;:
+
+<programlisting>
+Datum       my_same(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(my_same);
+
+Datum
+my_same(PG_FUNCTION_ARGS)
+{
+    prefix_range *v1 = PG_GETARG_PREFIX_RANGE_P(0);
+    prefix_range *v2 = PG_GETARG_PREFIX_RANGE_P(1);
+    bool       *result = (bool *) PG_GETARG_POINTER(2);
+
+    *result = my_eq(v1, v2);
+    PG_RETURN_POINTER(result);
+}
+</programlisting>
+
+        Pour des raisons historiques, la fonction <function>same</function> ne
+	renvoie pas seulement un résultat booléen&nbsp;; à la place, il doit
+	enregistrer le drapeau à l'emplacement indiqué par le troisième argument.
+      </para>
+     </listitem>
+    </varlistentry>
+
+  </variablelist>
+
+</sect1>
+
+<sect1 id="gist-examples">
+ <title>Exemples</title>
+
+ <para>
+  La distribution source de <productname>PostgreSQL</productname> inclut
+  plusieurs exemples de méthodes d'indexation implantées selon
+  <acronym>GiST</acronym>. Le système principal fournit des fonctionnalités
+  de recherche plein texte (indexation des <type>tsvector</type> et
+  <type>tsquery</type>) ainsi que des fonctionnalités équivalentes aux R-Tree
+  pour certains types de données géométriques
+  (voir <filename>src/backend/access/gist/gistproc.c</filename>). Les modules
+  <filename>contrib</filename> suivants contiennent aussi des classes d'opérateur
+  <acronym>GiST</acronym>&nbsp;:
+ </para>
+ 
+ <variablelist>
+  <varlistentry>
+   <term>btree_gist</term>
+   <listitem>
+    <para>Fonctionnalités équivalentes aux B-Tree pour plusieurs types de
+    données</para>
+   </listitem>
+  </varlistentry>
+
+  <varlistentry>
+   <term>cube</term>
+   <listitem>
+    <para>Indexation de cubes multi-dimensionnels</para>
+   </listitem>
+  </varlistentry>
+
+  <varlistentry>
+   <term>hstore</term>
+   <listitem>
+    <para>Module pour le stockage des paires (clé, valeur)</para>
+   </listitem>
+  </varlistentry>
+
+  <varlistentry>
+   <term>intarray</term>
+   <listitem>
+    <para>RD-Tree pour tableaux uni-dimensionnels de valeurs int4</para>
+   </listitem>
+  </varlistentry>
+
+  <varlistentry>
+   <term>ltree</term>
+   <listitem>
+    <para>Indexation des structures de type arbre</para>
+   </listitem>
+  </varlistentry>
+
+  <varlistentry>
+   <term>pg_trgm</term>
+   <listitem>
+    <para>Similarité textuelle par correspondance de trigrammes</para>
+   </listitem>
+  </varlistentry>
+
+  <varlistentry>
+   <term>seg</term>
+   <listitem>
+    <para>Indexation pour les <quote>nombres
+     flottants</quote></para>
+   </listitem>
+  </varlistentry>
+ </variablelist>
+
+</sect1>
+
+<sect1 id="gist-recovery">
+ <title>Récupération après un arrêt brutal</title>
+
+ <para>
+  Il est généralement suffisant de rejouer les traces WAL pour restaurer l'intégrité d'un
+  index GiST après un arrêt brutal de la base de données. Néanmoins, il existe
+  quelques cas particuliers pour lesquels l'état de l'index n'est pas
+  entièrement reconstruit. L'index reste fonctionnellement correct mais
+  les performances peuvent se trouver dégradées. Lorsque cela
+  arrive, l'index peut être réparé par <command>VACUUM</command> de sa table, ou
+  par reconstruction avec <command>REINDEX</command>. Dans certains cas, un simple
+  <command>VACUUM</command> ne suffit pas et un <command>VACUUM FULL</command>
+  ou un <command>REINDEX</command> est nécessaire. Ce besoin est indiqué par
+  la survenue d'un tel message&nbsp;:
+<programlisting>LOG:  index NNN/NNN/NNN needs VACUUM or REINDEX to finish crash recovery
+</programlisting>
+  ou le message suivant lors d'insertions dans l'index&nbsp;:
+<programlisting>LOG:  index "FOO" needs VACUUM or REINDEX to finish crash recovery
+</programlisting>
+  Si un simple <command>VACUUM</command> est incapable de réaliser
+  complètement la récupération, l'avertissement suivant est envoyé&nbsp;:
+<programlisting>NOTICE:  index "FOO" needs VACUUM FULL or REINDEX to finish crash recovery
+</programlisting>
+ </para>
+</sect1>
+
+</chapter>

Deleted: traduc/tags/tv840rc2/storage.xml
===================================================================
--- traduc/trunk/postgresql/storage.xml	2009-06-23 22:14:31 UTC (rev 1352)
+++ traduc/tags/tv840rc2/storage.xml	2009-06-27 10:41:54 UTC (rev 1355)
@@ -1,867 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-15"?>
-<!-- Dernière modification
-     le       $Date$
-     par      $Author$
-     révision $Revision$ -->
-
-<chapter id="storage">
-
-<title>Stockage physique de la base de données</title>
-
-<para>
-Ce chapitre fournit un aperçu du format de stockage physique utilisé par les
-bases de données <productname>PostgreSQL</productname>.
-</para>
-
-<sect1 id="storage-file-layout">
-
-<title>Emplacement des fichiers de la base de données</title>
-
-<para>
-Cette section décrit le format de stockage au niveau des fichiers et
-répertoires.
-</para>
-
-<para>
-Toutes les données nécessaires à un groupe de bases de données sont stockées
-dans le répertoire data du groupe, habituellement référencé en tant que
-<varname>PGDATA</varname> (d'après le nom de la variable d'environnement qui peut
-être utilisé pour le définir). Un emplacement courant pour <varname>PGDATA</varname>
-est <filename>/var/lib/pgsql/data</filename>. Plusieurs groupes, gérés par différentes
-instances du serveur, peuvent exister sur la même machine.
-</para>
-
-<para>
-Le répertoire <varname>PGDATA</varname> contient plusieurs sous-répertoires et
-fichiers de contrôle, comme indiqué dans le <xref linkend="pgdata-contents-table"/>. 
-En plus de ces éléments requis, les fichiers
-de configuration du groupe, <filename>postgresql.conf</filename>,
-<filename>pg_hba.conf</filename> et <filename>pg_ident.conf</filename> sont
-traditionnellement stockés dans <varname>PGDATA</varname> (bien qu'il soit possible de
-les conserver ailleurs à partir de la version 8.0 de
-<productname>PostgreSQL</productname>).
-</para>
-
-<table tocentry="1" id="pgdata-contents-table">
-<title>Contenu de <varname>PGDATA</varname></title>
-<tgroup cols="2">
-<colspec colnum="1" colwidth="0.5*"/>
-<colspec colnum="2" colwidth="1.5*"/>
-<thead>
-<row>
-<entry>Élément</entry>
-<entry>Description</entry>
-</row>
-</thead>
-
-<tbody>
-
-<row>
- <entry><filename>PG_VERSION</filename></entry>
- <entry>Un fichier contenant le numéro de version majeur de
-  <productname>PostgreSQL</productname></entry>
-</row>
-
-<row>
- <entry><filename>base</filename></entry>
- <entry>Sous-répertoire contenant les sous-répertoires par base de
-  données</entry>
-</row>
-
-<row>
- <entry><filename>global</filename></entry>
- <entry>Sous-répertoire contenant les tables communes au groupe, telles que
-  <structname>pg_database</structname></entry>
-</row>
-
-<row>
- <entry><filename>pg_clog</filename></entry>
- <entry>Sous-répertoire contenant les données d'état de validation des
-  transactions</entry>
-</row>
-
-<row>
- <entry><filename>pg_multixact</filename></entry>
- <entry>Sous-répertoire contenant des données sur l'état des
-  multi-transactions (utilisé pour les verrous de lignes partagées)</entry> 
-</row>
-
-<row>
- <entry><filename>pg_stat_tmp</filename></entry>
- <entry>Sous-répertoire contenant les fichiers temporaires pour le sous-système
-  des statistiques</entry>
-</row>
-
-<row>
- <entry><filename>pg_subtrans</filename></entry>
- <entry>Sous-répertoire contenant les données d'états des
-  sous-transaction</entry>
-</row>
-
-<row>
- <entry><filename>pg_tblspc</filename></entry>
- <entry>Sous-répertoire contenant les liens symboliques vers les espaces
-  logiques</entry>
-</row>
-
-<row>
- <entry><filename>pg_twophase</filename></entry>
- <entry>Sous-répertoire contenant les fichiers d'état pour les transactions
-  préparées</entry>
-</row>
-
-<row>
- <entry><filename>pg_xlog</filename></entry>
- <entry>Sous-répertoire contenant les fichiers WAL (Write Ahead Log)</entry>
-</row>
-
-<row>
- <entry><filename>postmaster.opts</filename></entry>
- <entry>Un fichier enregistrant les options en ligne de commande avec
-  lesquelles le serveur a été lancé la dernière fois</entry>
-</row>
-
-<row>
- <entry><filename>postmaster.pid</filename></entry>
- <entry>Un fichier verrou enregistrant le PID courant du serveur et l'identifiant
-  du segment de mémoire partagé (absent après l'arrêt du serveur)</entry>
-</row>
-
-</tbody>
-</tgroup>
-</table>
-
-<para>
-Pour chaque base de données dans le groupe, il existe un sous-répertoire dans
-<varname>PGDATA</varname><filename>/base</filename>, nommé d'après l'OID de la base de données
-dans <structname>pg_database</structname>. Ce sous-répertoire est l'emplacement par
-défaut pour les fichiers de la base de données; en particulier, ses
-catalogues système sont stockés ici.
-</para>
-
-<para>
-Chaque table et index sont stockés dans un fichier séparé, nommé d'après le
-numéro <firstterm>filenode</firstterm> de la table ou de l'index, lequel se
-trouve dans <structname>pg_class</structname>.<structfield>relfilenode</structfield>.
-En plus du fichier principal (appelé aussi «&nbsp;main fork&nbsp;»), chaque
-table et index a une <firstterm>carte des espaces libres</firstterm> (voir
-<xref linkend="storage-fsm"/>), qui stocke des informations sur les emplacements
-libres dans la relation. La carte des espace libre est stockée dans un fichier
-nommé par le numéro relfilenode à qui est ajouté le suffixe
-<literal>_fsm</literal>. Les tables ont aussi un fichier pour la <firstterm>carte de
-visibilité</firstterm>, de suffixe <literal>_vm</literal>, pour tracer les pages connues
-pour n'avoir aucune ligne morte.
-La carte de visibilité est décrite plus bas dans <xref linkend="storage-vm"/>.
-</para>
-
-<caution>
-<para>
-Notez que, bien que le filenode de la table correspond souvent à son OID,
-cela n'est <emphasis>pas</emphasis> nécessairement le cas; certaines
-opérations, comme <command>TRUNCATE</command>, <command>REINDEX</command>,
-<command>CLUSTER</command> et quelques formes d'<command>ALTER TABLE</command>, peuvent
-modifier le filenode tout en préservant l'OID. Évitez de supposer que filenode
-et OID sont identiques.
-</para>
-</caution>
-
-<para>
-Quand une table ou un index dépasse 1&nbsp;Go, il est divisé en
-<firstterm>segments</firstterm> d'un&nbsp;Go. Le nom du fichier du premier
-segment est identique au filenode&nbsp;; les segments suivants sont nommés
-filenode.1, filenode.2, etc. Cette disposition évite des problèmes sur les
-plateformes qui ont des limitations sur les tailles des fichiers.
-(Actuellement, 1&nbsp;Go est la taille du segment par défaut. Cette taille est
-ajustable en utilisant l'option <option>--with-segsize</option> pour configure
-avant de construire <productname>PostgreSQL</productname>.)
-En principe, les fichiers de la carte des espaces libres et de la carte de
-visibilité pourraient aussi nécessiter plusieurs segments, bien qu'il y a
-peu de chance que cela arrive réellement.
-Le contenu des tables et des index est discuté plus
-en détails dans <xref linkend="storage-page-layout"/>.
-</para>
-
-<para>
-Une table contenant des colonnes avec des entrées potentiellement volumineuses
-aura une table <firstterm>TOAST</firstterm> associée, qui est
-utilisée pour le stockage de valeurs de champs trop importantes pour
-conserver des lignes adéquates.
-<structname>pg_class</structname>.<structfield>reltoastrelid</structfield> établit un lien entre
-une table et sa table <acronym>TOAST</acronym>, si elle existe. Voir <xref
-linkend="storage-toast"/> pour plus d'informations.
-</para>
-
-<para>
-Les tablespaces rendent ce scénario plus compliqués. Chaque espace
-logique défini par l'utilisateur contient un lien symbolique dans le répertoire
-<varname>PGDATA</varname><filename>/pg_tblspc</filename>, pointant vers le répertoire physique
-du tablespace (comme spécifié dans sa commande <command>CREATE
-TABLESPACE</command>). Le lien symbolique est nommé d'après l'OID du tablespace.
-À l'intérieur du répertoire du tablespace, il existe un sous-répertoire 
-pour chacune des bases de données contenant des éléments dans ce tablespace. Ce
-sous-répertoire est nommé d'après l'OID de la base. Les tables de
-ce répertoire suivent le schéma de nommage des filenodes. Le tablespace
-<literal>pg_default</literal> n'est pas accédé via <filename>pg_tblspc</filename> mais
-correspond à <varname>PGDATA</varname><filename>/base</filename>. De façon similaire,
-le tablespace <literal>pg_global</literal> n'est pas accédé via 
-<filename>pg_tblspc</filename> mais correspond à <varname>PGDATA</varname><filename>/global</filename>.
-</para>
-
-<para>
-Les fichiers temporaires (pour des opérations comme le tri de plus de données
-que ce que la mémoire peut contenir) sont créés à l'intérieur de <varname>PGDATA</varname><filename>/base/pgsql_tmp</filename>,
-ou dans un sous-répertoire <filename>pgsql_tmp</filename> du répertoire du
-tablespace si un tablespace autre que <literal>pg_default</literal> est
-indiqué pour eux. Le nom du fichier temporaire est de la forme
-<filename>pgsql_tmp<replaceable>PPP</replaceable>.<replaceable>NNN</replaceable></filename>,
-où <replaceable>PPP</replaceable> est le PID du serveur propriétaire et
-<replaceable>NNN</replaceable> distingue les différents fichiers temporaires de ce
-serveur.
-</para>
-
-</sect1>
-
-<sect1 id="storage-toast">
-
-<title>TOAST</title>
-
-    <indexterm>
-     <primary>TOAST</primary>
-    </indexterm>
-    <indexterm><primary>sliced bread</primary><see>TOAST</see></indexterm>
-
-<para>
-Cette section fournit un aperçu de <acronym>TOAST</acronym> (<foreignphrase>The
-Oversized-Attribute Storage Technique</foreignphrase>, la technique de
-stockage des attributs trop grands).
-</para>
-
-<para>
-Puisque <productname>PostgreSQL</productname> utilise une taille de page fixe
-(habituellement 8&nbsp;Ko) et n'autorise pas qu'une ligne s'étende sur plusieurs
-pages. Du coup, il n'est pas possible de stocker de grandes valeurs directement
-dans les champs. Pour dépasser cette limitation, les valeurs de champ
-volumineuses sont compressées et/ou divisées en plusieurs lignes physiques. Ceci
-survient de façon transparente pour l'utilisateur, avec seulement un petit
-impact sur le code du serveur. Cette technique est connu sous l'acronyme
-affectueux de <acronym>TOAST</acronym> (ou <quote>the best thing since sliced
-bread</quote>).
-</para>
-
-<para>
-Seuls certains types de données supportent <acronym>TOAST</acronym> &mdash; il n'est
-pas nécessaire d'imposer cette surcharge sur les types de données qui ne 
-produisent pas de gros volumes. Pour supporter 
-<acronym>TOAST</acronym>, un type de données doit avoir une représentation 
-(<firstterm>varlena</firstterm>) à longueur variable, dans laquelle les 32 premiers bits
-contiennent la longueur totale de la valeur en octets (ceci incluant la
-longueur elle-même). <acronym>TOAST</acronym> n'a aucune contrainte supplémentaire
-sur la représentation. Toutes les fonctions niveau C qui gèrent un type données
-supportant <acronym>TOAST</acronym> doivent faire attention à gérer les valeurs en
-entrée <acronym>TOAST</acronym>ées. (Ceci se fait normalement en appelant
-<function>PG_DETOAST_DATUM</function> avant de faire quoi que ce soit avec une valeur
-en entrée; mais dans certains cas, des approches plus efficaces sont possibles.)
-</para>
-
-<para>
-<acronym>TOAST</acronym> récupère deux bits du mot contenant la longueur
-d'un varlena (ceux de poids fort sur les machines big-endian, ceux de poids
-faible sur les machines little-endian), limitant du coup la taille logique
-de toute valeur d'un type de données <acronym>TOAST</acronym> à 1&nbsp;Go
-(2<superscript>30</superscript> - 1 octets). Quand les deux bits sont à
-zéro, la valeur est une valeur non <acronym>TOAST</acronym>é du type de
-données et les bits restants dans le mot contenant la longueur indique
-la taille total du datum (incluant ce mot) en octets. Quand le bit de poids
-fort (ou de poids faible) est à un, la valeur a un en-tête de seulement
-un octet alors qu'un en-tête normal en fait quatre. Les bits restants
-donne la taille total du datum (incluant ce mot) en octets. Il reste un
-cas spécial&nbsp;: si les bits restants sont tous à zéro (ce qui est
-impossible étant donné que le mot indiquant la longueur est inclut dans
-la taille), la valeur est un pointeur vers une donnée stockée dans une table
-TOAST séparée (la taille d'un pointeur TOAST est indiquée dans le second
-octet du datum). Les valeurs dont l'en-tête fait un seul octet ne sont pas
-alignées sur une limite particulière. Enfin, quand le bit de poids fort
-(ou de poids faible) est supprimé mais que le bit adjacent vaut un, le
-contenu du datum est compressé et doit être décompresser avant utilisation.
-Dans ce cas, les bits restants du mot contenant la longueur indiquent la
-taille totale du datum compressé, pas celles des données au départ. Notez
-que la compression est aussi possible pour les données de la table TOAST
-mais l'en-tête varlena n'indique pas si c'est le cas &mdash; le contenu
-du pointeur TOAST le précise.
-</para>
-
-<para>
-Si une des colonnes d'une table est <acronym>TOAST</acronym>-able, la table disposera
-d'une table <acronym>TOAST</acronym> associé, dont l'OID est stockée dans l'entrée
-<structname>pg_class</structname>.<structfield>reltoastrelid</structfield> de la table. Les valeurs
-<acronym>TOAST</acronym>ées hors-ligne sont conservées dans la table <acronym>TOAST</acronym>
-comme décrit avec plus de détails ci-dessous.
-</para>
-
-<para>
-La technique de compression utilisée est un simple et rapide membre de la
-famille des techniques de compression LZ. Voir <filename>src/backend/utils/adt/pg_lzcompress.c</filename> pour les
-détails.
-</para>
-
-<para>
-Les valeurs hors-ligne sont divisées (après compression si nécessaire) en
-morceaux d'au plus <literal>TOAST_MAX_CHUNK_SIZE</literal> octets (par défaut,
-cette valeur est choisie pour que quatre morceaux de ligne tiennent sur une
-page, d'où les 2000 octets). Chaque morceau est stocké comme une ligne séparée dans la table
-<acronym>TOAST</acronym> de la table propriétaire. Chaque table <acronym>TOAST</acronym>
-contient les colonnes <structfield>chunk_id</structfield> (un OID identifiant la valeur
-<acronym>TOAST</acronym>ée particulière), <structfield>chunk_seq</structfield> (un numéro de
-séquence pour le morceau de la valeur) et <structfield>chunk_data</structfield> (la donnée
-réelle du morceau). Un index unique sur <structfield>chunk_id</structfield> et
-<structfield>chunk_seq</structfield> offre une récupération rapide des valeurs. Un
-pointeur datum représentant une valeur <acronym>TOAST</acronym>ée hors-ligne a par conséquent 
-besoin de stocker l'OID de la table <acronym>TOAST</acronym> dans laquelle chercher
-et l'OID de la valeur spécifique (son <structfield>chunk_id</structfield>). Par commodité, 
-les pointeurs datums stockent aussi la taille logique du datum (taille
-de la donnée originale non compressée) et la taille stockée réelle (différente
-si la compression a été appliquée). À partir des octets d'en-tête varlena,
-la taille totale d'un pointeur datum <acronym>TOAST</acronym> est par conséquent de 18 octets
-quelque soit la taille réelle de la valeur représentée.
-</para>
-
-<para>
-Le code <acronym>TOAST</acronym> est déclenché seulement quand une valeur de ligne
-à stocker dans une table est plus grande que <symbol>TOAST_TUPLE_THRESHOLD</symbol> octets (habituellement
-2&nbsp;Ko). Le code <acronym>TOAST</acronym> compressera et/ou déplacera les valeurs
-de champ hors la ligne jusqu'à ce que la valeur de la ligne soit plus petite que
-<symbol>TOAST_TUPLE_TARGET</symbol> octets  (habituellement là-aussi
-2&nbsp;Ko) ou que plus aucun gain ne puisse être réalisé. 
-Lors d'une opération UPDATE, les valeurs des champs non modifiées sont habituellement
-préservées telles quelles&nbsp;; donc un UPDATE sur une ligne avec des valeurs hors
-ligne n'induit pas de coûts à cause de <acronym>TOAST</acronym> si aucune des valeurs
-hors-ligne n'est modifiée.
-</para>
-
-<para>
-Le code <acronym>TOAST</acronym> connaît quatre stratégies différentes pour stocker
-les colonnes <acronym>TOAST</acronym>-ables&nbsp;:
-
-   <itemizedlist>
-    <listitem>
-     <para>
-      <literal>PLAIN</literal> empêche soit la compression soit le stockage
-      hors-ligne&nbsp;; de plus, il désactive l'utilisation d'en-tête sur
-      un octet pour les types varlena. Ceci est la seule stratégie possible
-      pour les colonnes des types de données non
-      <acronym>TOAST</acronym>-ables.
-     </para>
-    </listitem>
-    <listitem>
-     <para>
-      <literal>EXTENDED</literal> permet à la fois la compression et le
-      stockage hors-ligne. Ceci est la valeur par défaut de la plupart des
-      types de données <acronym>TOAST</acronym>-ables. La compression sera tentée en
-      premier, ensuite le stockage hors-ligne si la ligne est toujours trop
-      grande.
-     </para>
-    </listitem>
-    <listitem>
-     <para>
-      <literal>EXTERNAL</literal> autorise le stockage hors-ligne mais pas la
-      compression. L'utilisation d'<literal>EXTERNAL</literal> rendra plus rapides les
-      opérations sur des sous-chaînes d'importantes colonnes de type
-      <type>text</type> et <type>bytea</type> (au dépens d'un
-      espace de stockage accrus) car ces opérations sont optimisées pour
-      récupérer seulement les parties requises de la valeur hors-ligne
-      lorsqu'elle n'est pas compressée.
-     </para>
-    </listitem>
-    <listitem>
-     <para>
-      <literal>MAIN</literal> autorise la compression mais pas le stockage
-      hors-ligne. (En réalité le stockage hors-ligne sera toujours réalisé
-      pour de telles colonnes mais seulement en dernier ressort s'il n'existe
-      aucune autre solution pour diminuer suffisamment la taille de la ligne.)
-     </para>
-    </listitem>
-   </itemizedlist>
-
-Chaque type de données <acronym>TOAST</acronym>-able spécifie une stratégie par défaut 
-pour les colonnes de ce type de donnée, mais la stratégie pour une colonne d'une table
-donnée peut être modifiée avec <command>ALTER TABLE SET STORAGE</command>.
-</para>
-
-<para>
-Cette combinaison a de nombreux avantages comparés à une approche plus directe
-comme autoriser le stockage des valeurs de lignes sur plusieurs pages. En
-supposant que les requêtes sont habituellement qualifiées par comparaison avec
-des valeurs de clé relativement petites, la grosse partie du travail de
-l'exécuteur sera réalisée en utilisant l'entrée principale de la ligne. Les
-grandes valeurs des attributs <acronym>TOAST</acronym>és seront seulement récupérées
-(si elles sont sélectionnées) au moment où l'ensemble de résultats est
-envoyé au client. Ainsi, la table principale est bien plus petite
-et un plus grand nombre de ses lignes tiennent dans le cache du tampon partagé, 
-ce qui ne serait pas le cas sans aucun stockage hors-ligne.
-Le tri l'utilise aussi, et les tris seront plus souvent réalisés entièrement
-en mémoire. Un petit test a montré qu'une table contenant des pages HTML
-typiques ainsi que leurs URL étaient stockées en à peu près la moitié de la
-taille des données brutes en incluant la table <acronym>TOAST</acronym> et que la
-table principale contenait moins de 10&nbsp;% de la totalité des données (les
-URL et quelques petites pages HTML). Il n'y avait pas de différence à l'exécution
-en comparaison avec une table non <acronym>TOAST</acronym>ée, dans laquelle toutes les
-pages HTLM avaient été coupées à 7&nbsp;Ko pour tenir.
-</para>
-
-</sect1>
-
-<sect1 id="storage-fsm">
-
-<title>Carte des espaces libres</title>
-
-<indexterm>
- <primary>Free Space Map</primary>
-</indexterm>
-<indexterm><primary>FSM</primary><see>Free Space Map</see></indexterm>
-
-<para>
-Chaque table et index, en dehors des index hash, a une carte des espaces libres
-(appelée aussi <acronym>FSM</acronym>, acronyme de <foreignphrase>Free Space
-Map</foreignphrase>) pour conserver le trace des emplacements disponibles dans
-la relation. Elle est stockée dans un fichier séparé du fichier des données. Le
-nom de fichier est le numéro relfilenode suivi du suffixe
-<literal>_fsm</literal>. Par exemple, si le relfilenode d'une relation est
-12345, la FSM est stockée dans un fichier appelé
-<filename>12345_fsm</filename>, dans même répertoire que celui utilisé pour le
-fichier des données.
-</para>
-
-<para>
-La carte des espaces libres est organisée comme un arbre de pages
-<acronym>FSM</acronym>. Les pages <acronym>FSM</acronym> de niveau bas stockent
-l'espace libre disponible dans chaque page de la relation. Les niveaux
-suppérieurs agrégent l'information des niveaux bas.
-</para>
-
-<para>
-À l'intérieur de chaque page <acronym>FSM</acronym> se trouve un arbre binaire
-stocké dans un tableau avec un octet par n&oelig;ud. Chaque n&oelig;ud final
-représente une page de la relation, ou une page FSM de niveau bas. Dans chaque
-n&oelig;ud non final, la valeur la plus haute des valeurs enfants est stockée.
-Du coup, la valeur maximum de tous les n&oelig;uds se trouve à la racine.
-</para>
-
-<para>
-Voir <filename>src/backend/storage/freespace/README</filename> pour plus de
-détails sur la façon dont la <acronym>FSM</acronym> est structurée, et comment
-elle est mise à jour et recherchée. Le module contrib
-<filename>contrib/pg_freespacemap</filename> peut être utilisé pour examiner
-l'information stockée dans les cartes d'espace libre (voir <xref
-linkend="pgfreespacemap"/>).
-</para>
-
-</sect1>
-
-<sect1 id="storage-vm">
-
-<title>Visibility Map</title>
-
-<indexterm>
- <primary>Visibility Map</primary>
-</indexterm>
-<indexterm><primary>VM</primary><see>Visibility Map</see></indexterm>
-
-<para>
-Each heap relation has a Visibility Map
-(VM) to keep track of which pages contain only tuples that are known to be
-visible to all active transactions. It's stored
-alongside the main relation data in a separate relation fork, named after the
-filenode number of the relation, plus a <literal>_vm</literal> suffix. For example,
-if the filenode of a relation is 12345, the VM is stored in a file called
-<filename>12345_vm</filename>, in the same directory as the main relation file.
-Note that indexes do not have VMs.
-</para>
-
-<para>
-The visibility map simply stores one bit per heap page. A set bit means
-that all tuples on the page are known to be visible to all transactions.
-This means that the page does not contain any tuples that need to be vacuumed;
-in future it might also be used to avoid visiting the page for visibility
-checks. The map is conservative in the sense that we
-make sure that whenever a bit is set, we know the condition is true, but if
-a bit is not set, it might or might not be true.
-</para>
-
-</sect1>
-
-<sect1 id="storage-page-layout">
-
-<title>Emplacement des pages de la base de données</title>
-
-<para>
-Cette section fournit un aperçu du format des pages utilisées par les tables et
-index de <productname>PostgreSQL</productname>.<footnote>
-  <para>
-    En réalité, les méthodes d'accès par index n'ont pas besoin d'utiliser ce 
-    format de page. Toutes les méthodes d'indexage existantes utilisent ce
-    format de base mais les données conservées dans les métapages des index
-    ne suivent habituellement pas les règles d'emplacement des éléments.
-  </para>
-</footnote>
-Les séquences et les tables <acronym>TOAST</acronym> tables sont formatées comme des
-tables standards.
-</para>
-
-<para>
-Dans l'explication qui suit, un <firstterm>octet</firstterm> contient huit
-bits. De plus, le terme <firstterm>élément</firstterm> fait référence à une
-valeur de données individuelle qui est stockée dans une page. Dans une table,
-un élément est une ligne&nbsp;; dans un index, un élément est une entrée
-d'index.
-</para>
-
-<para>
-Chaque table et index est stocké comme un tableau de <firstterm>pages</firstterm> d'une
-taille fixe (habituellement 8&nbsp;Ko, bien qu'une taille de page différente
-peut être sélectionnée lors de la compilation du serveur). Dans une table,
-toutes les pages sont logiquement équivalentes pour qu'un élément (ligne)
-particulier puisse être stocké dans n'importe quelle page. Dans les index, la
-première page est généralement réservée comme <firstterm>métapage</firstterm> contenant
-des informations de contrôle, et il peut exister différents types de pages à
-l'intérieur de l'index, suivant la méthode d'accès à l'index. Les tables ont
-aussi une carte de visibilité dans un fichier de suffixe <literal>_vm</literal>,
-pour tracer les pages dont on sait qu'elles ne contiennent pas de lignes mortes
-et qui n'ont pas du coup besoin de VACUUM.
-</para>
-
-<para>
-<xref linkend="page-table"/> affiche le contenu complet d'une page. Il existe
-cinq parties pour chaque page.
-</para>
-
-<table tocentry="1" id="page-table">
-<title>Disposition générale d'une page</title>
-<titleabbrev>Disposition d'une page</titleabbrev>
-<tgroup cols="2">
-<colspec colnum="1" colwidth="0.5*"/>
-<colspec colnum="2" colwidth="1.5*"/>
-<thead>
-<row>
-<entry>Élément</entry>
-<entry>Description</entry>
-</row>
-</thead>
-
-<tbody>
-
-<row>
- <entry>PageHeaderData</entry>
- <entry>Longueur de 24 octets. Contient des informations générales sur la page y compris
-  des pointeurs sur les espaces libres.</entry>
-</row>
-
-<row>
- <entry>ItemIdData</entry>
- <entry>Tableau de paires (décalage,longueur) pointant sur les éléments réels.
-  Quatre octets par élément.</entry>
-</row>
-
-<row>
- <entry>Free space</entry>
- <entry>L'espace non alloué. Les pointeurs de nouveaux éléments sont alloués
-  à partir du début de cette région, les nouveaux éléments à partir de la
-  fin.</entry>
-</row>
-
-<row>
- <entry>Items</entry>
- <entry>Les éléments eux-mêmes.</entry>
-</row>
-
-<row>
- <entry>Special space</entry>
- <entry>Données spécifiques des méthodes d'accès aux index. Différentes
-  méthodes stockent différentes données. Vide pour les tables
-  ordinaires.</entry>
-</row>
-
-</tbody>
-</tgroup>
-</table>
-
- <para>
-
-  Les 24 premiers octets de chaque page consistent en un en-tête de page
-  (PageHeaderData). Son format est détaillé dans <xref
-  linkend="pageheaderdata-table"/>. Les deux premiers champs traquent l'entrée
-  WAL la plus récente relative à cette page. Ensuite se trouve un champ de
-  deux octets contenant des drapeaux. Ils sont suivis par trois
-  champs d'entiers sur deux octets (<structfield>pd_lower</structfield>,
-  <structfield>pd_upper</structfield> et
-  <structfield>pd_special</structfield>). Ils contiennent des décalages
-  d'octets à partir du début de la page jusqu'au début de l'espace non alloué,
-  jusqu'à la fin de l'espace non alloué, et jusqu'au début de l'espace spécial.
-  Les deux octets suivants de l'en-tête de page,
-  <structfield>pd_pagesize_version</structfield>, stockent à la fois la taille
-  de la page et un indicateur de versoin. À partir de la version 8.3 de
-  <productname>PostgreSQL</productname>, le numéro de version est 4&nbsp;; 
-  <productname>PostgreSQL</productname> 8.1 et 8.2 ont utilisé le numéro de version 3&nbsp;; 
-  <productname>PostgreSQL</productname> 8.0 a utilisé le numéro de version 2&nbsp;;
-  <productname>PostgreSQL</productname> 7.3 et 7.4 ont utilisé le numéro de
-  version 1&nbsp;; les versions précédentes utilisaient le numéro de version 0.
-  (La disposition fondamentale de la page et le format de l'en-tête n'ont pas changé
-  dans la plupart de ces versions mais la disposition de l'en-tête des lignes de tête a
-  changé.) La taille de la page est seulement présente comme vérification
-  croisée&nbsp;; il n'existe pas de support pour avoir plus d'une taille de
-  page dans une installation.
-  Le dernier champ est une aide indiquant si traiter la page serait
-  profitable&nbsp;: il garde l'information sur le plus vieux XMAX non traité
-  de la page.
- </para>
- 
- <table tocentry="1" id="pageheaderdata-table">
- <title>Disposition de PageHeaderData</title>
- <titleabbrev>Disposition de PageHeaderData</titleabbrev>
- <tgroup cols="4">   
-  <colspec colnum="1" colwidth="0.8*"/>
-  <colspec colnum="2" colwidth="0.5*"/>
-  <colspec colnum="3" colwidth="0.5*"/>
-  <colspec colnum="4" colwidth="2.2*"/>
- <thead>
-  <row> 
-   <entry>Champ</entry>
-   <entry>Type</entry>
-   <entry>Longueur</entry>
-   <entry>Description</entry>
-  </row>
- </thead>
- <tbody>
-  <row>
-   <entry>pd_lsn</entry>
-   <entry>XLogRecPtr</entry>
-   <entry>8 octets</entry>
-   <entry>LSN&nbsp;: octet suivant le dernier octet de l'enregistrement
-    xlog pour la dernière modification de cette page</entry>
-  </row>
-  <row>
-   <entry>pd_tli</entry>
-   <entry>uint16</entry>
-   <entry>2 octets</entry>
-   <entry>TimeLineID de la dernière modification (seulement les 16 bits de
-     poids faible)</entry>
-  </row>
-  <row>
-   <entry>pd_flags</entry>
-   <entry>uint16</entry>
-   <entry>2 octets</entry>
-   <entry>Bits d'état</entry>
-  </row>
-  <row>
-   <entry>pd_lower</entry>
-   <entry>LocationIndex</entry>
-   <entry>2 octets</entry>
-   <entry>Décalage jusqu'au début de l'espace libre</entry>
-  </row>
-  <row>
-   <entry>pd_upper</entry>
-   <entry>LocationIndex</entry>
-   <entry>2 octets</entry>
-   <entry>Décalage jusqu'à la fin de l'espace libre</entry>
-  </row>
-  <row>
-   <entry>pd_special</entry>
-   <entry>LocationIndex</entry>
-   <entry>2 octets</entry>
-   <entry>Décalage jusqu'au début de l'espace spécial</entry>
-  </row>
-  <row>
-   <entry>pd_pagesize_version</entry>
-   <entry>uint16</entry>
-   <entry>2 octets</entry>
-   <entry>Taille de la page et disposition de l'information du numéro de
-    version</entry>
-  </row>
-  <row>
-   <entry>pd_prune_xid</entry>
-   <entry>TransactionId</entry>
-   <entry>4 bytes</entry>
-   <entry>Plus vieux XMAX non traité sur la page, ou zéro si aucun</entry>
-  </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
-  Tous les détails se trouvent dans
-  <filename>src/include/storage/bufpage.h</filename>.
- </para>
-
- <para>
-
-  Après l'en-tête de la page se trouvent les identificateurs d'élément 
-  (<type>ItemIdData</type>), chacun nécessitant quatre octets. Un identificateur
-  d'élément contient un décalage d'octet vers le début d'un élément, sa
-  longueur en octets, et quelques bits d'attributs qui affectent son
-  interprétation. Les nouveaux identificateurs d'éléments sont alloués si
-  nécessaire à partir du début de l'espace non alloué. Le nombre d'identificateurs
-  d'éléments présents peut être déterminé en regardant
-  <structfield>pd_lower</structfield>, qui est augmenté pour allouer un nouvel
-  identificateur. Comme un identificateur d'élément n'est jamais déplacé tant qu'il
-  n'est pas libéré, son index pourrait être utilisé sur une base à long terme
-  pour référencer un élément, même quand l'élément lui-même est déplacé le long de
-  la page pour compresser l'espace libre. En fait, chaque pointeur vers un
-  élément (<type>ItemPointer</type>, aussi connu sous le nom de
-  <type>CTID</type>), créé par <productname>PostgreSQL</productname> consiste
-  en un numéro de page et l'index de l'identificateur d'élément.
-
- </para>
-
- <para>
- 
-  Les éléments eux-mêmes sont stockés dans l'espace alloué en marche arrière,
-  à partir de la fin de l'espace non alloué. La structure exacte varie
-  suivant le contenu de la table. Les tables et les séquences utilisent toutes
-  les deux une structure nommée <type>HeapTupleHeaderData</type>, décrite
-  ci-dessous.
-
- </para>
- 
- <para>
- 
-  La section finale est la <quote>section spéciale</quote> qui pourrait
-  contenir tout ce que les méthodes d'accès souhaitent stocker. Par exemple,
-  les index b-tree stockent des liens vers les enfants gauche et droit de la
-  page ainsi que quelques autres données sur la structure de l'index. Les
-  tables ordinaires n'utilisent pas du tout de section spéciale (indiquée
-  en configurant <structfield>pd_special</structfield> à la taille de la page).
-  
- </para>
- 
- <para>
-
-  Toutes les lignes de la table sont structurées de la même façon. Il existe
-  un en-tête à taille fixe (occupant 23 octets sur la plupart des machines),
-  suivi par un bitmap NULL optionnel, un champ ID de l'objet optionnel et les
-  données de l'utilisateur. L'en-tête est détaillé dans <xref
-  linkend="heaptupleheaderdata-table"/>. Les données réelles de l'utilisateur
-  (les colonnes de la ligne) commencent àu décalage indiqué par
-  <structfield>t_hoff</structfield>, qui doit toujours être un multiple de la distance
-  MAXALIGN pour la plateforme. Le bitmap NULL est seulement présent si le bit
-  <firstterm>HEAP_HASNULL</firstterm> est initialisé dans
-  <structfield>t_infomask</structfield>. S'il est présent, il commence juste
-  après l'en-tête fixe et occupe suffisamment d'octets pour avoir un bit par colonne
-  de données (c'est-à-dire <structfield>t_natts</structfield> bits ensemble). Dans cette
-  liste de bits, un bit 1 indique une valeur non NULL, un bit 0 une valeur
-  NULL. Quand le bitmap n'est pas présent, toutes les colonnes sont supposées
-  non NULL. L'ID de l'objet est seulement présent si le bit
-  <firstterm>HEAP_HASOID</firstterm> est initialisé dans
-  <structfield>t_infomask</structfield>. S'il est présent, il apparaît juste
-  avant la limite <structfield>t_hoff</structfield>. Tout ajout nécessaire pour faire
-  de <structfield>t_hoff</structfield> un multiple de MAXALIGN apparaîtra entre le 
-  bitmap NULL et l'ID de l'objet. (Ceci nous assure en retour que l'ID de
-  l'objet est convenablement aligné.)
-  
- </para>
- 
- <table tocentry="1" id="heaptupleheaderdata-table">
- <title>Disposition de HeapTupleHeaderData</title>
- <titleabbrev>Disposition de HeapTupleHeaderData</titleabbrev>
- <tgroup cols="4">
-  <colspec colnum="1" colwidth="0.5*"/>
-  <colspec colnum="2" colwidth="0.5*"/>
-  <colspec colnum="3" colwidth="0.5*"/>
-  <colspec colnum="4" colwidth="2.5*"/>
- <thead>
-  <row> 
-   <entry>Champ</entry>
-   <entry>Type</entry>
-   <entry>Longueur</entry>
-   <entry>Description</entry>
-  </row>
- </thead>
- <tbody>
-  <row>
-   <entry>t_xmin</entry>
-   <entry>TransactionId</entry>
-   <entry>4 octets</entry>
-   <entry>XID d'insertion</entry>
-  </row>
-  <row>
-   <entry>t_xmax</entry>
-   <entry>TransactionId</entry>
-   <entry>4 octets</entry>
-   <entry>XID de suppression</entry>
-  </row>
-  <row>
-   <entry>t_cid</entry>
-   <entry>CommandId</entry>
-   <entry>4 octets</entry>
-   <entry>CID d'insertion et de suppression (surcharge avec t_xvac)</entry>
-  </row>
-  <row>
-   <entry>t_xvac</entry>
-   <entry>TransactionId</entry>
-   <entry>4 octets</entry>
-   <entry>XID pour l'opération VACUUM déplaçant une version de ligne</entry>
-  </row>
-  <row>
-   <entry>t_ctid</entry>
-   <entry>ItemPointerData</entry>
-   <entry>6 octets</entry>
-   <entry>TID en cours pour cette version de ligne ou pour une version plus
-    récente</entry>
-  </row>
-  <row>
-   <entry>t_infomask2</entry>
-   <entry>int16</entry>
-   <entry>2 octets</entry>
-   <entry>nombre d'attributs et quelques bits d'état</entry>
-  </row>
-  <row>
-   <entry>t_infomask</entry>
-   <entry>uint16</entry>
-   <entry>2 octets</entry>
-   <entry>différents bits d'options (flag bits)</entry>
-  </row>
-  <row>
-   <entry>t_hoff</entry>
-   <entry>uint8</entry>
-   <entry>1 octet</entry>
-   <entry>décalage vers les données utilisateur</entry>
-  </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
-   Tous les détails sont disponibles dans
-   <filename>src/include/access/htup.h</filename>.
- </para>
-
- <para>
- 
-  Interpréter les données réelles peut seulement se faire avec des informations
-  obtenues à partir d'autres tables, principalement
-  <structname>pg_attribute</structname>. Les valeurs clés nécessaires pour
-  identifier les emplacements des champs sont
-  <structfield>attlen</structfield> et <structfield>attalign</structfield>.
-  Il n'existe aucun moyen pour obtenir directement un attribut particulier,
-  sauf quand il n'y a que des champs de largeur fixe et aucune colonne NULL.
-  Tout ceci est emballé dans les fonctions
-  <firstterm>heap_getattr</firstterm>, <firstterm>fastgetattr</firstterm>
-  et <firstterm>heap_getsysattr</firstterm>.
- </para>
- <para>
-
-  Pour lire les données, vous avez besoin d'examinez chaque attribut à son
-  tour. Commencez par vérifier si le champ est NULL en fonction du bitmap NULL.
-  S'il l'est, allez au suivant. Puis, assurez-vous que vous avez le bon
-  alignement. Si le champ est un champ à taille fixe, alors tous les octets
-  sont placés simplement. S'il s'agit d'un champ à taille variable
-  (attlen = -1), alors c'est un peu plus compliqué. Tous les types de données
-  à longueur variable partagent la même structure commune d'en-tête,
-  <type>struct varlena</type>, qui inclut la longueur totale de la valeur stockée
-  et quelques bits d'option. Suivant les options, les données pourraient être
-  soit dans la table de base soit dans une table <acronym>TOAST</acronym>&nbsp;;
-  elles pourraient aussi être compressées (voir <xref 
-  linkend="storage-toast"/>).
-  
- </para>
-</sect1>
-
-</chapter>

Copied: traduc/tags/tv840rc2/storage.xml (from rev 1353, traduc/trunk/postgresql/storage.xml)
===================================================================
--- traduc/tags/tv840rc2/storage.xml	                        (rev 0)
+++ traduc/tags/tv840rc2/storage.xml	2009-06-27 10:41:54 UTC (rev 1355)
@@ -0,0 +1,868 @@
+<?xml version="1.0" encoding="ISO-8859-15"?>
+<!-- Dernière modification
+     le       $Date$
+     par      $Author$
+     révision $Revision$ -->
+
+<chapter id="storage">
+
+<title>Stockage physique de la base de données</title>
+
+<para>
+Ce chapitre fournit un aperçu du format de stockage physique utilisé par les
+bases de données <productname>PostgreSQL</productname>.
+</para>
+
+<sect1 id="storage-file-layout">
+
+<title>Emplacement des fichiers de la base de données</title>
+
+<para>
+Cette section décrit le format de stockage au niveau des fichiers et
+répertoires.
+</para>
+
+<para>
+Toutes les données nécessaires à un groupe de bases de données sont stockées
+dans le répertoire data du groupe, habituellement référencé en tant que
+<varname>PGDATA</varname> (d'après le nom de la variable d'environnement qui peut
+être utilisé pour le définir). Un emplacement courant pour <varname>PGDATA</varname>
+est <filename>/var/lib/pgsql/data</filename>. Plusieurs groupes, gérés par différentes
+instances du serveur, peuvent exister sur la même machine.
+</para>
+
+<para>
+Le répertoire <varname>PGDATA</varname> contient plusieurs sous-répertoires et
+fichiers de contrôle, comme indiqué dans le <xref linkend="pgdata-contents-table"/>. 
+En plus de ces éléments requis, les fichiers
+de configuration du groupe, <filename>postgresql.conf</filename>,
+<filename>pg_hba.conf</filename> et <filename>pg_ident.conf</filename> sont
+traditionnellement stockés dans <varname>PGDATA</varname> (bien qu'il soit possible de
+les conserver ailleurs à partir de la version 8.0 de
+<productname>PostgreSQL</productname>).
+</para>
+
+<table tocentry="1" id="pgdata-contents-table">
+<title>Contenu de <varname>PGDATA</varname></title>
+<tgroup cols="2">
+<colspec colnum="1" colwidth="0.5*"/>
+<colspec colnum="2" colwidth="1.5*"/>
+<thead>
+<row>
+<entry>Élément</entry>
+<entry>Description</entry>
+</row>
+</thead>
+
+<tbody>
+
+<row>
+ <entry><filename>PG_VERSION</filename></entry>
+ <entry>Un fichier contenant le numéro de version majeur de
+  <productname>PostgreSQL</productname></entry>
+</row>
+
+<row>
+ <entry><filename>base</filename></entry>
+ <entry>Sous-répertoire contenant les sous-répertoires par base de
+  données</entry>
+</row>
+
+<row>
+ <entry><filename>global</filename></entry>
+ <entry>Sous-répertoire contenant les tables communes au groupe, telles que
+  <structname>pg_database</structname></entry>
+</row>
+
+<row>
+ <entry><filename>pg_clog</filename></entry>
+ <entry>Sous-répertoire contenant les données d'état de validation des
+  transactions</entry>
+</row>
+
+<row>
+ <entry><filename>pg_multixact</filename></entry>
+ <entry>Sous-répertoire contenant des données sur l'état des
+  multi-transactions (utilisé pour les verrous de lignes partagées)</entry> 
+</row>
+
+<row>
+ <entry><filename>pg_stat_tmp</filename></entry>
+ <entry>Sous-répertoire contenant les fichiers temporaires pour le sous-système
+  des statistiques</entry>
+</row>
+
+<row>
+ <entry><filename>pg_subtrans</filename></entry>
+ <entry>Sous-répertoire contenant les données d'états des
+  sous-transaction</entry>
+</row>
+
+<row>
+ <entry><filename>pg_tblspc</filename></entry>
+ <entry>Sous-répertoire contenant les liens symboliques vers les espaces
+  logiques</entry>
+</row>
+
+<row>
+ <entry><filename>pg_twophase</filename></entry>
+ <entry>Sous-répertoire contenant les fichiers d'état pour les transactions
+  préparées</entry>
+</row>
+
+<row>
+ <entry><filename>pg_xlog</filename></entry>
+ <entry>Sous-répertoire contenant les fichiers WAL (Write Ahead Log)</entry>
+</row>
+
+<row>
+ <entry><filename>postmaster.opts</filename></entry>
+ <entry>Un fichier enregistrant les options en ligne de commande avec
+  lesquelles le serveur a été lancé la dernière fois</entry>
+</row>
+
+<row>
+ <entry><filename>postmaster.pid</filename></entry>
+ <entry>Un fichier verrou enregistrant le PID courant du serveur et l'identifiant
+  du segment de mémoire partagé (absent après l'arrêt du serveur)</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+<para>
+Pour chaque base de données dans le groupe, il existe un sous-répertoire dans
+<varname>PGDATA</varname><filename>/base</filename>, nommé d'après l'OID de la base de données
+dans <structname>pg_database</structname>. Ce sous-répertoire est l'emplacement par
+défaut pour les fichiers de la base de données; en particulier, ses
+catalogues système sont stockés ici.
+</para>
+
+<para>
+Chaque table et index sont stockés dans un fichier séparé, nommé d'après le
+numéro <firstterm>filenode</firstterm> de la table ou de l'index, lequel se
+trouve dans <structname>pg_class</structname>.<structfield>relfilenode</structfield>.
+En plus du fichier principal (appelé aussi «&nbsp;main fork&nbsp;»), chaque
+table et index a une <firstterm>carte des espaces libres</firstterm> (voir
+<xref linkend="storage-fsm"/>), qui stocke des informations sur les emplacements
+libres dans la relation. La carte des espace libre est stockée dans un fichier
+nommé par le numéro relfilenode à qui est ajouté le suffixe
+<literal>_fsm</literal>. Les tables ont aussi un fichier pour la <firstterm>carte de
+visibilité</firstterm>, de suffixe <literal>_vm</literal>, pour tracer les pages connues
+pour n'avoir aucune ligne morte.
+La carte de visibilité est décrite plus bas dans <xref linkend="storage-vm"/>.
+</para>
+
+<caution>
+<para>
+Notez que, bien que le filenode de la table correspond souvent à son OID,
+cela n'est <emphasis>pas</emphasis> nécessairement le cas; certaines
+opérations, comme <command>TRUNCATE</command>, <command>REINDEX</command>,
+<command>CLUSTER</command> et quelques formes d'<command>ALTER TABLE</command>, peuvent
+modifier le filenode tout en préservant l'OID. Évitez de supposer que filenode
+et OID sont identiques.
+</para>
+</caution>
+
+<para>
+Quand une table ou un index dépasse 1&nbsp;Go, il est divisé en
+<firstterm>segments</firstterm> d'un&nbsp;Go. Le nom du fichier du premier
+segment est identique au filenode&nbsp;; les segments suivants sont nommés
+filenode.1, filenode.2, etc. Cette disposition évite des problèmes sur les
+plateformes qui ont des limitations sur les tailles des fichiers.
+(Actuellement, 1&nbsp;Go est la taille du segment par défaut. Cette taille est
+ajustable en utilisant l'option <option>--with-segsize</option> pour configure
+avant de construire <productname>PostgreSQL</productname>.)
+En principe, les fichiers de la carte des espaces libres et de la carte de
+visibilité pourraient aussi nécessiter plusieurs segments, bien qu'il y a
+peu de chance que cela arrive réellement.
+Le contenu des tables et des index est discuté plus
+en détails dans <xref linkend="storage-page-layout"/>.
+</para>
+
+<para>
+Une table contenant des colonnes avec des entrées potentiellement volumineuses
+aura une table <firstterm>TOAST</firstterm> associée, qui est
+utilisée pour le stockage de valeurs de champs trop importantes pour
+conserver des lignes adéquates.
+<structname>pg_class</structname>.<structfield>reltoastrelid</structfield> établit un lien entre
+une table et sa table <acronym>TOAST</acronym>, si elle existe. Voir <xref
+linkend="storage-toast"/> pour plus d'informations.
+</para>
+
+<para>
+Les tablespaces rendent ce scénario plus compliqués. Chaque espace
+logique défini par l'utilisateur contient un lien symbolique dans le répertoire
+<varname>PGDATA</varname><filename>/pg_tblspc</filename>, pointant vers le répertoire physique
+du tablespace (comme spécifié dans sa commande <command>CREATE
+TABLESPACE</command>). Le lien symbolique est nommé d'après l'OID du tablespace.
+À l'intérieur du répertoire du tablespace, il existe un sous-répertoire 
+pour chacune des bases de données contenant des éléments dans ce tablespace. Ce
+sous-répertoire est nommé d'après l'OID de la base. Les tables de
+ce répertoire suivent le schéma de nommage des filenodes. Le tablespace
+<literal>pg_default</literal> n'est pas accédé via <filename>pg_tblspc</filename> mais
+correspond à <varname>PGDATA</varname><filename>/base</filename>. De façon similaire,
+le tablespace <literal>pg_global</literal> n'est pas accédé via 
+<filename>pg_tblspc</filename> mais correspond à <varname>PGDATA</varname><filename>/global</filename>.
+</para>
+
+<para>
+Les fichiers temporaires (pour des opérations comme le tri de plus de données
+que ce que la mémoire peut contenir) sont créés à l'intérieur de <varname>PGDATA</varname><filename>/base/pgsql_tmp</filename>,
+ou dans un sous-répertoire <filename>pgsql_tmp</filename> du répertoire du
+tablespace si un tablespace autre que <literal>pg_default</literal> est
+indiqué pour eux. Le nom du fichier temporaire est de la forme
+<filename>pgsql_tmp<replaceable>PPP</replaceable>.<replaceable>NNN</replaceable></filename>,
+où <replaceable>PPP</replaceable> est le PID du serveur propriétaire et
+<replaceable>NNN</replaceable> distingue les différents fichiers temporaires de ce
+serveur.
+</para>
+
+</sect1>
+
+<sect1 id="storage-toast">
+
+<title>TOAST</title>
+
+    <indexterm>
+     <primary>TOAST</primary>
+    </indexterm>
+    <indexterm><primary>sliced bread</primary><see>TOAST</see></indexterm>
+
+<para>
+Cette section fournit un aperçu de <acronym>TOAST</acronym> (<foreignphrase>The
+Oversized-Attribute Storage Technique</foreignphrase>, la technique de
+stockage des attributs trop grands).
+</para>
+
+<para>
+Puisque <productname>PostgreSQL</productname> utilise une taille de page fixe
+(habituellement 8&nbsp;Ko) et n'autorise pas qu'une ligne s'étende sur plusieurs
+pages. Du coup, il n'est pas possible de stocker de grandes valeurs directement
+dans les champs. Pour dépasser cette limitation, les valeurs de champ
+volumineuses sont compressées et/ou divisées en plusieurs lignes physiques. Ceci
+survient de façon transparente pour l'utilisateur, avec seulement un petit
+impact sur le code du serveur. Cette technique est connu sous l'acronyme
+affectueux de <acronym>TOAST</acronym> (ou <quote>the best thing since sliced
+bread</quote>).
+</para>
+
+<para>
+Seuls certains types de données supportent <acronym>TOAST</acronym> &mdash; il n'est
+pas nécessaire d'imposer cette surcharge sur les types de données qui ne 
+produisent pas de gros volumes. Pour supporter 
+<acronym>TOAST</acronym>, un type de données doit avoir une représentation 
+(<firstterm>varlena</firstterm>) à longueur variable, dans laquelle les 32 premiers bits
+contiennent la longueur totale de la valeur en octets (ceci incluant la
+longueur elle-même). <acronym>TOAST</acronym> n'a aucune contrainte supplémentaire
+sur la représentation. Toutes les fonctions niveau C qui gèrent un type données
+supportant <acronym>TOAST</acronym> doivent faire attention à gérer les valeurs en
+entrée <acronym>TOAST</acronym>ées. (Ceci se fait normalement en appelant
+<function>PG_DETOAST_DATUM</function> avant de faire quoi que ce soit avec une valeur
+en entrée; mais dans certains cas, des approches plus efficaces sont possibles.)
+</para>
+
+<para>
+<acronym>TOAST</acronym> récupère deux bits du mot contenant la longueur
+d'un varlena (ceux de poids fort sur les machines big-endian, ceux de poids
+faible sur les machines little-endian), limitant du coup la taille logique
+de toute valeur d'un type de données <acronym>TOAST</acronym> à 1&nbsp;Go
+(2<superscript>30</superscript> - 1 octets). Quand les deux bits sont à
+zéro, la valeur est une valeur non <acronym>TOAST</acronym>é du type de
+données et les bits restants dans le mot contenant la longueur indique
+la taille total du datum (incluant ce mot) en octets. Quand le bit de poids
+fort (ou de poids faible) est à un, la valeur a un en-tête de seulement
+un octet alors qu'un en-tête normal en fait quatre. Les bits restants
+donne la taille total du datum (incluant ce mot) en octets. Il reste un
+cas spécial&nbsp;: si les bits restants sont tous à zéro (ce qui est
+impossible étant donné que le mot indiquant la longueur est inclut dans
+la taille), la valeur est un pointeur vers une donnée stockée dans une table
+TOAST séparée (la taille d'un pointeur TOAST est indiquée dans le second
+octet du datum). Les valeurs dont l'en-tête fait un seul octet ne sont pas
+alignées sur une limite particulière. Enfin, quand le bit de poids fort
+(ou de poids faible) est supprimé mais que le bit adjacent vaut un, le
+contenu du datum est compressé et doit être décompresser avant utilisation.
+Dans ce cas, les bits restants du mot contenant la longueur indiquent la
+taille totale du datum compressé, pas celles des données au départ. Notez
+que la compression est aussi possible pour les données de la table TOAST
+mais l'en-tête varlena n'indique pas si c'est le cas &mdash; le contenu
+du pointeur TOAST le précise.
+</para>
+
+<para>
+Si une des colonnes d'une table est <acronym>TOAST</acronym>-able, la table disposera
+d'une table <acronym>TOAST</acronym> associé, dont l'OID est stockée dans l'entrée
+<structname>pg_class</structname>.<structfield>reltoastrelid</structfield> de la table. Les valeurs
+<acronym>TOAST</acronym>ées hors-ligne sont conservées dans la table <acronym>TOAST</acronym>
+comme décrit avec plus de détails ci-dessous.
+</para>
+
+<para>
+La technique de compression utilisée est un simple et rapide membre de la
+famille des techniques de compression LZ. Voir <filename>src/backend/utils/adt/pg_lzcompress.c</filename> pour les
+détails.
+</para>
+
+<para>
+Les valeurs hors-ligne sont divisées (après compression si nécessaire) en
+morceaux d'au plus <literal>TOAST_MAX_CHUNK_SIZE</literal> octets (par défaut,
+cette valeur est choisie pour que quatre morceaux de ligne tiennent sur une
+page, d'où les 2000 octets). Chaque morceau est stocké comme une ligne séparée dans la table
+<acronym>TOAST</acronym> de la table propriétaire. Chaque table <acronym>TOAST</acronym>
+contient les colonnes <structfield>chunk_id</structfield> (un OID identifiant la valeur
+<acronym>TOAST</acronym>ée particulière), <structfield>chunk_seq</structfield> (un numéro de
+séquence pour le morceau de la valeur) et <structfield>chunk_data</structfield> (la donnée
+réelle du morceau). Un index unique sur <structfield>chunk_id</structfield> et
+<structfield>chunk_seq</structfield> offre une récupération rapide des valeurs. Un
+pointeur datum représentant une valeur <acronym>TOAST</acronym>ée hors-ligne a par conséquent 
+besoin de stocker l'OID de la table <acronym>TOAST</acronym> dans laquelle chercher
+et l'OID de la valeur spécifique (son <structfield>chunk_id</structfield>). Par commodité, 
+les pointeurs datums stockent aussi la taille logique du datum (taille
+de la donnée originale non compressée) et la taille stockée réelle (différente
+si la compression a été appliquée). À partir des octets d'en-tête varlena,
+la taille totale d'un pointeur datum <acronym>TOAST</acronym> est par conséquent de 18 octets
+quelque soit la taille réelle de la valeur représentée.
+</para>
+
+<para>
+Le code <acronym>TOAST</acronym> est déclenché seulement quand une valeur de ligne
+à stocker dans une table est plus grande que <symbol>TOAST_TUPLE_THRESHOLD</symbol> octets (habituellement
+2&nbsp;Ko). Le code <acronym>TOAST</acronym> compressera et/ou déplacera les valeurs
+de champ hors la ligne jusqu'à ce que la valeur de la ligne soit plus petite que
+<symbol>TOAST_TUPLE_TARGET</symbol> octets  (habituellement là-aussi
+2&nbsp;Ko) ou que plus aucun gain ne puisse être réalisé. 
+Lors d'une opération UPDATE, les valeurs des champs non modifiées sont habituellement
+préservées telles quelles&nbsp;; donc un UPDATE sur une ligne avec des valeurs hors
+ligne n'induit pas de coûts à cause de <acronym>TOAST</acronym> si aucune des valeurs
+hors-ligne n'est modifiée.
+</para>
+
+<para>
+Le code <acronym>TOAST</acronym> connaît quatre stratégies différentes pour stocker
+les colonnes <acronym>TOAST</acronym>-ables&nbsp;:
+
+   <itemizedlist>
+    <listitem>
+     <para>
+      <literal>PLAIN</literal> empêche soit la compression soit le stockage
+      hors-ligne&nbsp;; de plus, il désactive l'utilisation d'en-tête sur
+      un octet pour les types varlena. Ceci est la seule stratégie possible
+      pour les colonnes des types de données non
+      <acronym>TOAST</acronym>-ables.
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      <literal>EXTENDED</literal> permet à la fois la compression et le
+      stockage hors-ligne. Ceci est la valeur par défaut de la plupart des
+      types de données <acronym>TOAST</acronym>-ables. La compression sera tentée en
+      premier, ensuite le stockage hors-ligne si la ligne est toujours trop
+      grande.
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      <literal>EXTERNAL</literal> autorise le stockage hors-ligne mais pas la
+      compression. L'utilisation d'<literal>EXTERNAL</literal> rendra plus rapides les
+      opérations sur des sous-chaînes d'importantes colonnes de type
+      <type>text</type> et <type>bytea</type> (au dépens d'un
+      espace de stockage accrus) car ces opérations sont optimisées pour
+      récupérer seulement les parties requises de la valeur hors-ligne
+      lorsqu'elle n'est pas compressée.
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      <literal>MAIN</literal> autorise la compression mais pas le stockage
+      hors-ligne. (En réalité le stockage hors-ligne sera toujours réalisé
+      pour de telles colonnes mais seulement en dernier ressort s'il n'existe
+      aucune autre solution pour diminuer suffisamment la taille de la ligne.)
+     </para>
+    </listitem>
+   </itemizedlist>
+
+Chaque type de données <acronym>TOAST</acronym>-able spécifie une stratégie par défaut 
+pour les colonnes de ce type de donnée, mais la stratégie pour une colonne d'une table
+donnée peut être modifiée avec <command>ALTER TABLE SET STORAGE</command>.
+</para>
+
+<para>
+Cette combinaison a de nombreux avantages comparés à une approche plus directe
+comme autoriser le stockage des valeurs de lignes sur plusieurs pages. En
+supposant que les requêtes sont habituellement qualifiées par comparaison avec
+des valeurs de clé relativement petites, la grosse partie du travail de
+l'exécuteur sera réalisée en utilisant l'entrée principale de la ligne. Les
+grandes valeurs des attributs <acronym>TOAST</acronym>és seront seulement récupérées
+(si elles sont sélectionnées) au moment où l'ensemble de résultats est
+envoyé au client. Ainsi, la table principale est bien plus petite
+et un plus grand nombre de ses lignes tiennent dans le cache du tampon partagé, 
+ce qui ne serait pas le cas sans aucun stockage hors-ligne.
+Le tri l'utilise aussi, et les tris seront plus souvent réalisés entièrement
+en mémoire. Un petit test a montré qu'une table contenant des pages HTML
+typiques ainsi que leurs URL étaient stockées en à peu près la moitié de la
+taille des données brutes en incluant la table <acronym>TOAST</acronym> et que la
+table principale contenait moins de 10&nbsp;% de la totalité des données (les
+URL et quelques petites pages HTML). Il n'y avait pas de différence à l'exécution
+en comparaison avec une table non <acronym>TOAST</acronym>ée, dans laquelle toutes les
+pages HTLM avaient été coupées à 7&nbsp;Ko pour tenir.
+</para>
+
+</sect1>
+
+<sect1 id="storage-fsm">
+
+<title>Carte des espaces libres</title>
+
+<indexterm>
+ <primary>Free Space Map</primary>
+</indexterm>
+<indexterm><primary>FSM</primary><see>Free Space Map</see></indexterm>
+
+<para>
+Chaque table et index, en dehors des index hash, a une carte des espaces libres
+(appelée aussi <acronym>FSM</acronym>, acronyme de <foreignphrase>Free Space
+Map</foreignphrase>) pour conserver le trace des emplacements disponibles dans
+la relation. Elle est stockée dans un fichier séparé du fichier des données. Le
+nom de fichier est le numéro relfilenode suivi du suffixe
+<literal>_fsm</literal>. Par exemple, si le relfilenode d'une relation est
+12345, la FSM est stockée dans un fichier appelé
+<filename>12345_fsm</filename>, dans même répertoire que celui utilisé pour le
+fichier des données.
+</para>
+
+<para>
+La carte des espaces libres est organisée comme un arbre de pages
+<acronym>FSM</acronym>. Les pages <acronym>FSM</acronym> de niveau bas stockent
+l'espace libre disponible dans chaque page de la relation. Les niveaux
+suppérieurs agrégent l'information des niveaux bas.
+</para>
+
+<para>
+À l'intérieur de chaque page <acronym>FSM</acronym> se trouve un arbre binaire
+stocké dans un tableau avec un octet par n&oelig;ud. Chaque n&oelig;ud final
+représente une page de la relation, ou une page FSM de niveau bas. Dans chaque
+n&oelig;ud non final, la valeur la plus haute des valeurs enfants est stockée.
+Du coup, la valeur maximum de tous les n&oelig;uds se trouve à la racine.
+</para>
+
+<para>
+Voir <filename>src/backend/storage/freespace/README</filename> pour plus de
+détails sur la façon dont la <acronym>FSM</acronym> est structurée, et comment
+elle est mise à jour et recherchée. Le module contrib
+<filename>contrib/pg_freespacemap</filename> peut être utilisé pour examiner
+l'information stockée dans les cartes d'espace libre (voir <xref
+linkend="pgfreespacemap"/>).
+</para>
+
+</sect1>
+
+<sect1 id="storage-vm">
+
+<title>Carte de visibilité</title>
+
+<indexterm>
+ <primary>Carte de visibilité</primary>
+</indexterm>
+<indexterm><primary>VM</primary><see>Carte de visibilité</see></indexterm>
+
+<para>
+Chaque relation a une carte de visibilité (<acronym>VM</acronym> acronyme de
+<foreignphrase>Visibility Map</foreignphrase>) pour garder trace des pages
+contenant seulement des lignes connues pour être visibles par toutes les
+transactions actives. Elle est stockée en dehors du fichier de données dans
+un fichier séparé nommé suivant le numéro relfilenode de la relation, auquel
+est ajouté le suffixe <literal>_vm</literal>. Par exemple, si le relfilenode
+de la relation est 12345, la VM est stockée dans un fichier appelé
+<filename>12345_vm</filename>, dans le même répertoire que celui du fichier
+de données. Notez que les index n'ont pas de VM.
+</para>
+
+<para>
+La carte de visibilité enregistre un bit par page. Un bit à 1 signifie
+que toutes les lignes de la page sont visibles par toutes les transactions.
+Cela signifie que le page ne contient pas de lignes nécessitant un VACUUM&nbsp;;
+dans le futur, cela pourra aussi être utilisé pour éviter de visiter la page
+lors de vérifications de visibilité. Chaque fois qu'un bit est à 1, la condition
+est vraie à coup sûr. Par contre, dans le cas contraire, la condition peut être
+vraie comme fausse.
+</para>
+
+</sect1>
+
+<sect1 id="storage-page-layout">
+
+<title>Emplacement des pages de la base de données</title>
+
+<para>
+Cette section fournit un aperçu du format des pages utilisées par les tables et
+index de <productname>PostgreSQL</productname>.<footnote>
+  <para>
+    En réalité, les méthodes d'accès par index n'ont pas besoin d'utiliser ce 
+    format de page. Toutes les méthodes d'indexage existantes utilisent ce
+    format de base mais les données conservées dans les métapages des index
+    ne suivent habituellement pas les règles d'emplacement des éléments.
+  </para>
+</footnote>
+Les séquences et les tables <acronym>TOAST</acronym> tables sont formatées comme des
+tables standards.
+</para>
+
+<para>
+Dans l'explication qui suit, un <firstterm>octet</firstterm> contient huit
+bits. De plus, le terme <firstterm>élément</firstterm> fait référence à une
+valeur de données individuelle qui est stockée dans une page. Dans une table,
+un élément est une ligne&nbsp;; dans un index, un élément est une entrée
+d'index.
+</para>
+
+<para>
+Chaque table et index est stocké comme un tableau de <firstterm>pages</firstterm> d'une
+taille fixe (habituellement 8&nbsp;Ko, bien qu'une taille de page différente
+peut être sélectionnée lors de la compilation du serveur). Dans une table,
+toutes les pages sont logiquement équivalentes pour qu'un élément (ligne)
+particulier puisse être stocké dans n'importe quelle page. Dans les index, la
+première page est généralement réservée comme <firstterm>métapage</firstterm> contenant
+des informations de contrôle, et il peut exister différents types de pages à
+l'intérieur de l'index, suivant la méthode d'accès à l'index. Les tables ont
+aussi une carte de visibilité dans un fichier de suffixe <literal>_vm</literal>,
+pour tracer les pages dont on sait qu'elles ne contiennent pas de lignes mortes
+et qui n'ont pas du coup besoin de VACUUM.
+</para>
+
+<para>
+<xref linkend="page-table"/> affiche le contenu complet d'une page. Il existe
+cinq parties pour chaque page.
+</para>
+
+<table tocentry="1" id="page-table">
+<title>Disposition générale d'une page</title>
+<titleabbrev>Disposition d'une page</titleabbrev>
+<tgroup cols="2">
+<colspec colnum="1" colwidth="0.5*"/>
+<colspec colnum="2" colwidth="1.5*"/>
+<thead>
+<row>
+<entry>Élément</entry>
+<entry>Description</entry>
+</row>
+</thead>
+
+<tbody>
+
+<row>
+ <entry>PageHeaderData</entry>
+ <entry>Longueur de 24 octets. Contient des informations générales sur la page y compris
+  des pointeurs sur les espaces libres.</entry>
+</row>
+
+<row>
+ <entry>ItemIdData</entry>
+ <entry>Tableau de paires (décalage,longueur) pointant sur les éléments réels.
+  Quatre octets par élément.</entry>
+</row>
+
+<row>
+ <entry>Free space</entry>
+ <entry>L'espace non alloué. Les pointeurs de nouveaux éléments sont alloués
+  à partir du début de cette région, les nouveaux éléments à partir de la
+  fin.</entry>
+</row>
+
+<row>
+ <entry>Items</entry>
+ <entry>Les éléments eux-mêmes.</entry>
+</row>
+
+<row>
+ <entry>Special space</entry>
+ <entry>Données spécifiques des méthodes d'accès aux index. Différentes
+  méthodes stockent différentes données. Vide pour les tables
+  ordinaires.</entry>
+</row>
+
+</tbody>
+</tgroup>
+</table>
+
+ <para>
+
+  Les 24 premiers octets de chaque page consistent en un en-tête de page
+  (PageHeaderData). Son format est détaillé dans <xref
+  linkend="pageheaderdata-table"/>. Les deux premiers champs traquent l'entrée
+  WAL la plus récente relative à cette page. Ensuite se trouve un champ de
+  deux octets contenant des drapeaux. Ils sont suivis par trois
+  champs d'entiers sur deux octets (<structfield>pd_lower</structfield>,
+  <structfield>pd_upper</structfield> et
+  <structfield>pd_special</structfield>). Ils contiennent des décalages
+  d'octets à partir du début de la page jusqu'au début de l'espace non alloué,
+  jusqu'à la fin de l'espace non alloué, et jusqu'au début de l'espace spécial.
+  Les deux octets suivants de l'en-tête de page,
+  <structfield>pd_pagesize_version</structfield>, stockent à la fois la taille
+  de la page et un indicateur de versoin. À partir de la version 8.3 de
+  <productname>PostgreSQL</productname>, le numéro de version est 4&nbsp;; 
+  <productname>PostgreSQL</productname> 8.1 et 8.2 ont utilisé le numéro de version 3&nbsp;; 
+  <productname>PostgreSQL</productname> 8.0 a utilisé le numéro de version 2&nbsp;;
+  <productname>PostgreSQL</productname> 7.3 et 7.4 ont utilisé le numéro de
+  version 1&nbsp;; les versions précédentes utilisaient le numéro de version 0.
+  (La disposition fondamentale de la page et le format de l'en-tête n'ont pas changé
+  dans la plupart de ces versions mais la disposition de l'en-tête des lignes de tête a
+  changé.) La taille de la page est seulement présente comme vérification
+  croisée&nbsp;; il n'existe pas de support pour avoir plus d'une taille de
+  page dans une installation.
+  Le dernier champ est une aide indiquant si traiter la page serait
+  profitable&nbsp;: il garde l'information sur le plus vieux XMAX non traité
+  de la page.
+ </para>
+ 
+ <table tocentry="1" id="pageheaderdata-table">
+ <title>Disposition de PageHeaderData</title>
+ <titleabbrev>Disposition de PageHeaderData</titleabbrev>
+ <tgroup cols="4">   
+  <colspec colnum="1" colwidth="0.8*"/>
+  <colspec colnum="2" colwidth="0.5*"/>
+  <colspec colnum="3" colwidth="0.5*"/>
+  <colspec colnum="4" colwidth="2.2*"/>
+ <thead>
+  <row> 
+   <entry>Champ</entry>
+   <entry>Type</entry>
+   <entry>Longueur</entry>
+   <entry>Description</entry>
+  </row>
+ </thead>
+ <tbody>
+  <row>
+   <entry>pd_lsn</entry>
+   <entry>XLogRecPtr</entry>
+   <entry>8 octets</entry>
+   <entry>LSN&nbsp;: octet suivant le dernier octet de l'enregistrement
+    xlog pour la dernière modification de cette page</entry>
+  </row>
+  <row>
+   <entry>pd_tli</entry>
+   <entry>uint16</entry>
+   <entry>2 octets</entry>
+   <entry>TimeLineID de la dernière modification (seulement les 16 bits de
+     poids faible)</entry>
+  </row>
+  <row>
+   <entry>pd_flags</entry>
+   <entry>uint16</entry>
+   <entry>2 octets</entry>
+   <entry>Bits d'état</entry>
+  </row>
+  <row>
+   <entry>pd_lower</entry>
+   <entry>LocationIndex</entry>
+   <entry>2 octets</entry>
+   <entry>Décalage jusqu'au début de l'espace libre</entry>
+  </row>
+  <row>
+   <entry>pd_upper</entry>
+   <entry>LocationIndex</entry>
+   <entry>2 octets</entry>
+   <entry>Décalage jusqu'à la fin de l'espace libre</entry>
+  </row>
+  <row>
+   <entry>pd_special</entry>
+   <entry>LocationIndex</entry>
+   <entry>2 octets</entry>
+   <entry>Décalage jusqu'au début de l'espace spécial</entry>
+  </row>
+  <row>
+   <entry>pd_pagesize_version</entry>
+   <entry>uint16</entry>
+   <entry>2 octets</entry>
+   <entry>Taille de la page et disposition de l'information du numéro de
+    version</entry>
+  </row>
+  <row>
+   <entry>pd_prune_xid</entry>
+   <entry>TransactionId</entry>
+   <entry>4 bytes</entry>
+   <entry>Plus vieux XMAX non traité sur la page, ou zéro si aucun</entry>
+  </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+  Tous les détails se trouvent dans
+  <filename>src/include/storage/bufpage.h</filename>.
+ </para>
+
+ <para>
+
+  Après l'en-tête de la page se trouvent les identificateurs d'élément 
+  (<type>ItemIdData</type>), chacun nécessitant quatre octets. Un identificateur
+  d'élément contient un décalage d'octet vers le début d'un élément, sa
+  longueur en octets, et quelques bits d'attributs qui affectent son
+  interprétation. Les nouveaux identificateurs d'éléments sont alloués si
+  nécessaire à partir du début de l'espace non alloué. Le nombre d'identificateurs
+  d'éléments présents peut être déterminé en regardant
+  <structfield>pd_lower</structfield>, qui est augmenté pour allouer un nouvel
+  identificateur. Comme un identificateur d'élément n'est jamais déplacé tant qu'il
+  n'est pas libéré, son index pourrait être utilisé sur une base à long terme
+  pour référencer un élément, même quand l'élément lui-même est déplacé le long de
+  la page pour compresser l'espace libre. En fait, chaque pointeur vers un
+  élément (<type>ItemPointer</type>, aussi connu sous le nom de
+  <type>CTID</type>), créé par <productname>PostgreSQL</productname> consiste
+  en un numéro de page et l'index de l'identificateur d'élément.
+
+ </para>
+
+ <para>
+ 
+  Les éléments eux-mêmes sont stockés dans l'espace alloué en marche arrière,
+  à partir de la fin de l'espace non alloué. La structure exacte varie
+  suivant le contenu de la table. Les tables et les séquences utilisent toutes
+  les deux une structure nommée <type>HeapTupleHeaderData</type>, décrite
+  ci-dessous.
+
+ </para>
+ 
+ <para>
+ 
+  La section finale est la <quote>section spéciale</quote> qui pourrait
+  contenir tout ce que les méthodes d'accès souhaitent stocker. Par exemple,
+  les index b-tree stockent des liens vers les enfants gauche et droit de la
+  page ainsi que quelques autres données sur la structure de l'index. Les
+  tables ordinaires n'utilisent pas du tout de section spéciale (indiquée
+  en configurant <structfield>pd_special</structfield> à la taille de la page).
+  
+ </para>
+ 
+ <para>
+
+  Toutes les lignes de la table sont structurées de la même façon. Il existe
+  un en-tête à taille fixe (occupant 23 octets sur la plupart des machines),
+  suivi par un bitmap NULL optionnel, un champ ID de l'objet optionnel et les
+  données de l'utilisateur. L'en-tête est détaillé dans <xref
+  linkend="heaptupleheaderdata-table"/>. Les données réelles de l'utilisateur
+  (les colonnes de la ligne) commencent àu décalage indiqué par
+  <structfield>t_hoff</structfield>, qui doit toujours être un multiple de la distance
+  MAXALIGN pour la plateforme. Le bitmap NULL est seulement présent si le bit
+  <firstterm>HEAP_HASNULL</firstterm> est initialisé dans
+  <structfield>t_infomask</structfield>. S'il est présent, il commence juste
+  après l'en-tête fixe et occupe suffisamment d'octets pour avoir un bit par colonne
+  de données (c'est-à-dire <structfield>t_natts</structfield> bits ensemble). Dans cette
+  liste de bits, un bit 1 indique une valeur non NULL, un bit 0 une valeur
+  NULL. Quand le bitmap n'est pas présent, toutes les colonnes sont supposées
+  non NULL. L'ID de l'objet est seulement présent si le bit
+  <firstterm>HEAP_HASOID</firstterm> est initialisé dans
+  <structfield>t_infomask</structfield>. S'il est présent, il apparaît juste
+  avant la limite <structfield>t_hoff</structfield>. Tout ajout nécessaire pour faire
+  de <structfield>t_hoff</structfield> un multiple de MAXALIGN apparaîtra entre le 
+  bitmap NULL et l'ID de l'objet. (Ceci nous assure en retour que l'ID de
+  l'objet est convenablement aligné.)
+  
+ </para>
+ 
+ <table tocentry="1" id="heaptupleheaderdata-table">
+ <title>Disposition de HeapTupleHeaderData</title>
+ <titleabbrev>Disposition de HeapTupleHeaderData</titleabbrev>
+ <tgroup cols="4">
+  <colspec colnum="1" colwidth="0.5*"/>
+  <colspec colnum="2" colwidth="0.5*"/>
+  <colspec colnum="3" colwidth="0.5*"/>
+  <colspec colnum="4" colwidth="2.5*"/>
+ <thead>
+  <row> 
+   <entry>Champ</entry>
+   <entry>Type</entry>
+   <entry>Longueur</entry>
+   <entry>Description</entry>
+  </row>
+ </thead>
+ <tbody>
+  <row>
+   <entry>t_xmin</entry>
+   <entry>TransactionId</entry>
+   <entry>4 octets</entry>
+   <entry>XID d'insertion</entry>
+  </row>
+  <row>
+   <entry>t_xmax</entry>
+   <entry>TransactionId</entry>
+   <entry>4 octets</entry>
+   <entry>XID de suppression</entry>
+  </row>
+  <row>
+   <entry>t_cid</entry>
+   <entry>CommandId</entry>
+   <entry>4 octets</entry>
+   <entry>CID d'insertion et de suppression (surcharge avec t_xvac)</entry>
+  </row>
+  <row>
+   <entry>t_xvac</entry>
+   <entry>TransactionId</entry>
+   <entry>4 octets</entry>
+   <entry>XID pour l'opération VACUUM déplaçant une version de ligne</entry>
+  </row>
+  <row>
+   <entry>t_ctid</entry>
+   <entry>ItemPointerData</entry>
+   <entry>6 octets</entry>
+   <entry>TID en cours pour cette version de ligne ou pour une version plus
+    récente</entry>
+  </row>
+  <row>
+   <entry>t_infomask2</entry>
+   <entry>int16</entry>
+   <entry>2 octets</entry>
+   <entry>nombre d'attributs et quelques bits d'état</entry>
+  </row>
+  <row>
+   <entry>t_infomask</entry>
+   <entry>uint16</entry>
+   <entry>2 octets</entry>
+   <entry>différents bits d'options (flag bits)</entry>
+  </row>
+  <row>
+   <entry>t_hoff</entry>
+   <entry>uint8</entry>
+   <entry>1 octet</entry>
+   <entry>décalage vers les données utilisateur</entry>
+  </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+   Tous les détails sont disponibles dans
+   <filename>src/include/access/htup.h</filename>.
+ </para>
+
+ <para>
+ 
+  Interpréter les données réelles peut seulement se faire avec des informations
+  obtenues à partir d'autres tables, principalement
+  <structname>pg_attribute</structname>. Les valeurs clés nécessaires pour
+  identifier les emplacements des champs sont
+  <structfield>attlen</structfield> et <structfield>attalign</structfield>.
+  Il n'existe aucun moyen pour obtenir directement un attribut particulier,
+  sauf quand il n'y a que des champs de largeur fixe et aucune colonne NULL.
+  Tout ceci est emballé dans les fonctions
+  <firstterm>heap_getattr</firstterm>, <firstterm>fastgetattr</firstterm>
+  et <firstterm>heap_getsysattr</firstterm>.
+ </para>
+ <para>
+
+  Pour lire les données, vous avez besoin d'examinez chaque attribut à son
+  tour. Commencez par vérifier si le champ est NULL en fonction du bitmap NULL.
+  S'il l'est, allez au suivant. Puis, assurez-vous que vous avez le bon
+  alignement. Si le champ est un champ à taille fixe, alors tous les octets
+  sont placés simplement. S'il s'agit d'un champ à taille variable
+  (attlen = -1), alors c'est un peu plus compliqué. Tous les types de données
+  à longueur variable partagent la même structure commune d'en-tête,
+  <type>struct varlena</type>, qui inclut la longueur totale de la valeur stockée
+  et quelques bits d'option. Suivant les options, les données pourraient être
+  soit dans la table de base soit dans une table <acronym>TOAST</acronym>&nbsp;;
+  elles pourraient aussi être compressées (voir <xref 
+  linkend="storage-toast"/>).
+  
+ </para>
+</sect1>
+
+</chapter>



Plus d'informations sur la liste de diffusion Trad