<!-- $Header: /usr/prj/pg/cvsroot/doc/doc/src/sgml/indices.sgml,v 1.6 2001/08/27 02:42:35 k-kondo Exp $ -->

<chapter id="indices">
 <!--  <title id="indices-title">Indices</title> -->
 <title id="indices-title">インデックス</title>
<indexterm><primary sortas="いんでっくす">インデックス</primary></indexterm>
 <para>
  <!-- Indices are a common way to enhance database performance.  An index
  allows the database server to find and retrieve specific rows much
  faster than it could do without an index.  But indices also add
  overhead to the database system as a whole, so they should be used
  sensibly. -->
  インデックスはデータベース性能を向上させるための一般的な方法です。インデックスがあると、ない場合に比べてデータベースサーバーが特定の行をずっと速く見つけ抽出できます。しかしインデックスはデータベース全体にとってはオーバーヘッドの追加となるため、繊細な注意が必要です。

 </para>


 <sect1 id="indices-intro">
  <!-- <title>Introduction</title> -->
  <title>序文</title>

  <para>
   <!-- The classical example for the need of an index is if there is a
   table similar to this: -->
   インデックスの必要性を示す古典的な例は、下記のようなテーブルです。</para>

<programlisting>
CREATE TABLE test1 (
    id integer,
    content varchar
);
</programlisting>
   <!-- and the application requires a lot of queries of the form -->
<para>このアプリケーションは以下のようなたくさんの問い合わせを必要とします。</para>
<programlisting>
SELECT content FROM test1 WHERE id = <replaceable>constant</replaceable>;
</programlisting>
   <!-- Ordinarily, the system would have to scan the entire
   <structname>test1</structname> table row by row to find all
   matching entries.  If there are a lot of rows in
   <structname>test1</structname> and only a few rows (possibly zero
   or one) returned by the query, then this is clearly an inefficient
   method.  If the system were instructed to maintain an index on the
   <structfield>id</structfield> column, then it could use a more
   efficient method for locating matching rows.  For instance, it
   might only have to walk a few levels deep into a search tree. -->

<para>普通は、システムはすべてのあてはまる項目を見つけるために<structname>test1</structname>テーブルを1行ごとにスキャンしなければいけません。もし<structname>test1</structname>にたくさんの行があり問い合わせが数行（おそらく0行か1行）しか返さない場合、それは明らかに効率が悪いメソッドです。もしシステムがインデックスを<structfield>id</structfield>カラム上に保ち続けるよう指示されていれば、あてはまる行を見つけるのにもっと効率のよいメソッドを使うことができます。たとえば、検索ツリーの中で数層しか進まなくてよいかもしれません。
  </para>

  <para>
   <!-- A similar approach is used in most books of non-fiction:  Terms and
   concepts that are frequently looked up by readers are collected in
   an alphabetic index at the end of the book.  The interested reader
   can scan the index relatively quickly and flip to the appropriate
   page, and would not have to read the entire book to find the
   interesting location.  As it is the task of the author to
   anticipate the items that the readers are most likely to look up,
   it is the task of the database programmer to foresee which indexes
   would be of advantage. -->

   ほとんどのノンフィクションの本では似たようなアプローチが使われています。読者が頻繁に調べる用語と概念は本の終わりにアルファベット順にまとめられています。興味を持った読者はインデックスを比較的速くスキャンし、見たいページに飛ぶことができるため、見たい場所を探すために本全部を読む必要がありません。読者が調べる可能性の高い単語を予測するのが著者の仕事であるように、どのインデックスが有益であるかを予測するのはデータベースプログラマの仕事です。
 
  </para>

  <para>
   <!-- The following command would be used to create the index on the
   <structfield>id</structfield> column, as discussed: -->

   <structfield>id</structfield>カラム上にインデックスを作るために下記のようなコマンドが使われます。</para>


<programlisting>
CREATE INDEX test1_id_index ON test1 (id);
</programlisting>
   <!-- The name <structname>test1_id_index</structname> can be chosen
   freely, but you should pick something that enables you to remember
   later what the index was for. -->

<para><structname>test1_id_index</structname>という名前は自由に選択されることができますが、あとでそのインデックスが何のためだったか思い出せるものを選ぶことが必要です。

  </para>

  <para>
   <!-- To remove an index, use the <command>DROP INDEX</command> command.
   Indices can be added and removed from tables at any time. -->
   インデックスを削除するためには<command>DROP INDEX</command>コマンドを使ってください。インデックスはいつでもテーブルに追加したり削除することができます。

  </para>

  <para>
   <!-- Once the index is created, no further intervention is required: the
   system will use the index when it thinks it would be more efficient
   than a sequential table scan.  But you may have to run the
   <command>VACUUM ANALYZE</command> command regularly to update
   statistics to allow the query planner to make educated decisions.
   Also read <xref linkend="performance-tips"> for information about
   how to find out whether an index is used and when and why the
   planner may choose to <emphasis>not</emphasis> use an index. -->

   一度インデックスが作られると、それ以上の干渉は必要ありません。システムは、順テーブルスキャンよりも効率が上がると思われる場合にインデックスを使うのです。しかし、問い合わせプランナが根拠のある決断を下すことを許すために、定期的に<command>VACUUM ANALYZE</command>を実行する必要があります。さらに、インデックスが使われているかどうか、いつそしてなぜプランナがインデックスをつかわ<emphasis>ない</emphasis>ことを選択したかを知るためには<xref linkend="performance-tips">を読んでください。

  </para>

  <para>
   <!-- Indices can also benefit <command>UPDATE</command>s and
   <command>DELETE</command>s with search conditions.  Note that a
   query or data manipulation commands can only use at most one index
   per table.  Indices can also be used in table join methods.  Thus,
   an index defined on a column that is part of a join condition can
   significantly speed up queries with joins. -->

   インデックスは、<command>UPDATE</command>や<command>DELETE</command>の検索条件にも役に立ちます。問い合わせやデータを扱うコマンドは最大でもテーブルごとに1つのインデックスしか使えないことに注意してください。インデックスはテーブル結合メソッドでも使うことができます。したがって、結合条件の一部である、カラム上で定義されたインデックスは、結合を使った問い合わせを著しく速めることができます。
  </para>

  <para>
   <!-- When an index is created, it has to be kept synchronized with the
   table.  This adds overhead to data manipulation operations.
   Therefore indices that are non-essential or do not get used at all
   should be removed. -->

   インデックスが作られると、テーブルと一致するように維持されなくてはいけません。これはデータを扱う演算にオーバーヘッドを加えます。したがって、重要ではないインデックスやまったく使われないインデックスは削除されるべきです。

  </para>
 </sect1>


 <sect1 id="indices-types">
  <!-- <title>Index Types</title> -->
  <title>インデックスの型</title>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="かた">型</secondary></indexterm>
<para>

   <!-- <productname>Postgres</productname> provides several index types:
   B-tree, R-tree, and Hash.  Each index type is more appropriate for
   a particular query type because of the algorithm it uses.  By
   default, the <command>CREATE INDEX</command> command will create a
   B-tree index, which fits the most common situations.  In
   particular, the <productname>Postgres</productname> query optimizer
   will consider using a B-tree index whenever an indexed column is
   involved in a comparison using one of these operators: -->

<productname>Postgres</productname>は、B-tree、R-tree、Hashといったインデックス型を提供しています。それぞれのインデックス型は、使うアルゴリズムのために、特定の問い合わせ型にふさわしいようになっています。デフォルトでは<command>CREATE INDEX</command>コマンドはB-treeインデックスを作ります。これは一般的な状況に適切です。特に<productname>Postgres</productname>の問い合わせオプティマイザは、インデックスのついたカラムが下記のような演算子のついた比較で使われるたびに、B-treeの使用を検討します。<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="かた">型</secondary><tertiary>B-tree</tertiary></indexterm>
</para>

   <simplelist type="inline">
    <member><literal>&lt;</literal></member>
    <member><literal>&lt;=</literal></member>
    <member><literal>=</literal></member>
    <member><literal>&gt;=</literal></member>
    <member><literal>&gt;</literal></member>
   </simplelist>

  <para>
   <!-- R-tree indices are especially suited for spacial data.  To create
   an R-tree index, use a command of the form -->

   R-treeインデックスは、特に空間的データに適しています。R-treeインデックスを作るためには、下記のようなコマンドを使ってください。<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="かた">型</secondary><tertiary>R-tree</tertiary></indexterm>
</para>

<synopsis>
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> USING RTREE (<replaceable>column</replaceable>);
</synopsis>
   <!-- The <productname>Postgres</productname> query optimizer will
   consider using an R-tree index whenever an indexed column is
   involved in a comparison using one of these operators: -->

<para>
<productname>Postgres</productname>の問い合わせオプティマイザは、インデックスのついたカラムが下記の演算子のいずれかを使った比較で使われるたびに、R-treeインデックスの使用を検討します。
</para>

   <simplelist type="inline">
    <member><literal>&lt;&lt;</literal></member>
    <member><literal>&amp;&lt;</literal></member>
    <member><literal>&amp;&gt;</literal></member>
    <member><literal>&gt;&gt;</literal></member>
    <member><literal>@</literal></member>
    <member><literal>~=</literal></member>
    <member><literal>&amp;&amp;</literal></member>
   </simplelist>
   <!-- (Refer to <xref linkend="functions-geometry"> about the meaning of
   these operators.) -->
<para>
これらの演算子の意味については、<xref linkend="functions-geometry">を参照してください。

  </para>

  <para>
   <!-- The query optimizer will consider using a hash index whenever an
   indexed column is involved in a comparison using the
   <literal>=</literal> operator.  The following command is used to
   create a hash index: -->

   問い合わせオプティマイザは、インデックスのついたカラムが<literal>=</literal>演算子を使った比較で使われるたびに、hashインデックスの使用を検討します。hashインデックスを作るためには下記のコマンドが使われます。<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="かた">型</secondary><tertiary>hash</tertiary></indexterm>
</para>

<synopsis>
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> USING HASH (<replaceable>column</replaceable>);
</synopsis>

   <note>
    <para>
     <!-- Because of the limited utility of hash indices, a B-tree index
     should generally be preferred over a hash index.  We do not have
     sufficient evidence that hash indices are actually faster than
     B-trees even for <literal>=</literal> comparisons.  Moreover,
     hash indices require coarser locks; see <xref
     linkend="locking-indices">. -->

     hashインデックスの限られた有用性のために、通常はB-treeインデックスのほうがhashインデックスよりも好まれます。<literal>=</literal>の比較でさえもB-treeよりもhashのほうが速いという確かな証拠はありません。さらにhashインデックスは粒度の粗いロックを必要とします（<xref linkend="locking-indices">を参照してください）。
    </para>
   </note>

  <para>
   <!-- The B-tree index is an implementation of Lehman-Yao
   high-concurrency B-trees.  The R-tree index method implements
   standard R-trees using Guttman's quadratic split algorithm.  The
   hash index is an implementation of Litwin's linear hashing.  We
   mention the algorithms used solely to indicate that all of these
   access methods are fully dynamic and do not have to be optimized
   periodically (as is the case with, for example, static hash access
   methods). -->

   B-treeインデックスはLehman-Yao高同時実行性B-treeの実装です。R-treeインデックスメソッドはGuttmanの二次分割アルゴリズムを使った標準R-treeを実装しています。hashインデックスはLitwinの線形ハッシュの実装です。ここでは、これらのアクセスメソッドは完全に動的であり、定期的に最適化される必要がない（たとえば、静的hashアクセスメソッドのような場合）ということを示すためだけにアルゴリズムについて言及しています。

  </para>
 </sect1>


 <sect1 id="indices-multicolumn">
  <!-- <title>Multi-Column Indices</title> -->
  <title>マルチカラムインデックス</title>
<indexterm><primary sortas="まるちからむいんでっくす">マルチカラムインデックス</primary></indexterm>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="まるちからむいんでっくす">マルチカラムインデックス</secondary></indexterm>
  <para>
   <!-- An index can be defined on more than one column.  For example, if
   you have a table of this form: -->

   インデックスは、1つ以上のカラムで定義することができます。たとえば、次のようなテーブルがあったとします。</para>

<programlisting>
CREATE TABLE test2 (
  major int,
  minor int,
  name varchar
);
</programlisting>
   <!-- (Say, you keep you your <filename class="directory">/dev</filename>
   directory in a database...) and you frequently make queries like -->
<para><filename class="directory">/dev</filename>ディレクトリの内容をデータベースに保持していて、頻繁に下記のような問い合わせを実行するとします。</para>

<programlisting>
SELECT name FROM test2 WHERE major = <replaceable>constant</replaceable> AND minor = <replaceable>constant</replaceable>;
</programlisting>
   <!-- then it may be appropriate to define an index on the columns 
   <structfield>major</structfield> and
   <structfield>minor</structfield> together, e.g.,-->

<para>この場合、インデックスを<structfield>major</structfield>カラムと<structfield>minor</structfield>カラムの両方で定義するのが適切かもしれません。</para>

<programlisting>
CREATE INDEX test2_mm_idx ON test2 (major, minor);
</programlisting>

  <para>
   <!-- Currently, only the B-tree implementation supports multi-column
   indices.  Up to 16 columns may be specified.  (This limit can be
   altered when building <productname>Postgres</productname>; see the
   file <filename>config.h</filename>.) -->

   現在では、B-treeの実装だけがマルチカラムインデックスをサポートしていて、16カラムまで指定することができます（この上限は<productname>Postgres</productname>を構築するときに変えることができます。<filename>config.h</filename>ファイルを参照してください）。

  </para>

  <para>
   <!-- The query optimizer can use a multi-column index for queries that
   involve the first <Parameter>n</parameter> consecutive columns in
   the index (when used with appropriate operators), up to the total
   number of columns specified in the index definition.  For example,
   an index on <literal>(a, b, c)</literal> can be used in queries
   involving all of <literal>a</literal>, <literal>b</literal>, and
   <literal>c</literal>, or in queries involving both
   <literal>a</literal> and <literal>b</literal>, or in queries
   involving only <literal>a</literal>, but not in other combinations.
   (In a query involving <literal>a</literal> and <literal>c</literal>
   the optimizer might choose to use the index for
   <literal>a</literal> only and treat <literal>c</literal> like an
   ordinary unindexed column.) -->

   問い合わせオプティマイザは、インデックスに最初の連続した<Parameter>n</parameter>カラム（適切な演算子と使われている場合）からインデックス定義で指定されたカラムの総数までを含む問い合わせに、マルチカラムインデックスを使うことができます。たとえば、<literal>(a, b, c)</literal>のインデックスは<literal>a</literal>、<literal>b</literal>、<literal>c</literal>のすべてを使う問い合わせ、もしくは<literal>a</literal>と<literal>b</literal>両方をを使う問い合わせ、または<literal>a</literal>のみを使う問い合わせの中で使われることができますが、それ以外の組み合わせでは使えません（<literal>a</literal>と<literal>c</literal>を使った問い合わせでは、オプティマイザは<literal>a</literal>にのみインデックスを使うことにし、<literal>c</literal>は通常のインデックスなしのカラムのように扱うかもしれません）。
  </para>



  <para>
   <!-- Multi-column indexes can only be used if the clauses involving the
   indexed columns are joined with <literal>AND</literal>.  For instance, -->

   マルチカラムインデックスは、インデックスのついたカラムが<literal>AND</literal>で結合されている場合にのみ使うことができます。たとえば、以下のような問い合わせを見てみましょう。</para>

<programlisting>
SELECT name FROM test2 WHERE major = <replaceable>constant</replaceable> OR minor = <replaceable>constant</replaceable>;
</programlisting>
   <!-- cannot make use of the index <structname>test2_mm_idx</structname>
   defined above to look up both columns.  (It can be used to look up
   only the <structfield>major</structfield> column, however.) -->

<para>この問い合わせ例では、両方のカラムを見つけるために、上で定義された<structname>test2_mm_idx</structname>を利用することができません（しかし<structfield>major</structfield>カラムを見つけるときだけは使うことができます）。

  </para>

  <para>
   <!-- Multi-column indices should be used sparingly.  Most of the time,
   an index on a single column is sufficient and saves space and time.
   Indexes with more than three columns are almost certainly
   inappropriate. -->
   マルチカラムインデックスは滅多に使われるべきではありません。大体の場合において、1つのカラムのインデックスは十分であり、ディスク領域と時間を節約します。3つ以上のインデックスを持つカラムはほぼ不適切であると断言できます。
  </para>
 </sect1>


 <sect1 id="indices-unique">
  <!-- <title>Unique Indices</title> -->
  <title>一意なインデックス</title>
<indexterm><primary sortas="いちいないんでっくす">一意なインデックス</primary></indexterm>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="いちいないんでっくす">一意なインデックス</secondary></indexterm>
  <para>
   <!-- Indexes may also be used to enforce uniqueness of a column's value,
   or the uniqueness of the combined values of more than one column. -->

   インデックスは、カラム値の一意性や、1つ以上のカラムを統合した値の一意性を強制するためにも使うことができます。
</para>

<synopsis>
CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <optional>, ...</optional>);
</synopsis>

<para>
   <!-- Only B-tree indices can be declared unique. -->
    B-treeインデックスだけが一意であると宣言されることができます。
  </para>

  <para>
   <!-- When an index is declared unique, multiple table rows with equal
   indexed values will not be allowed.  NULL values are not considered
   equal. -->

   インデックスが一意であると宣言されると、同じインデックスの値を持つテーブルの複数の行は許されなくなります。NULL値は同じとはみなされません。

  </para>

  <para>
   <!-- <productname>PostgreSQL</productname> automatically creates unique
   indices when a table is declared with a unique constraint or a
   primary key, on the columns that make up the primary key or unique
   columns (a multi-column index, if appropriate), to enforce that
   constraint.  A unique index can be added to a table at any later
   time, to add a unique constraint.  (But a primary key cannot be
   added after table creation.) -->

   <productname>PostgreSQL</productname>は、一意な制約か主キーを持つテーブルが宣言されると、自動的に一意なインデックスを作ります。これは制約を強制するために、主キーか一意なカラム（必要ならば、マルチカラムインデックス）を作るカラム上に作られます。一意な制約を追加するために、一意なインデックスはその後いつでもテーブルに追加することができます（しかし、主キーはテーブル作成後に追加することができません）。
  </para>
 </sect1>


 <sect1 id="indices-functional">
  <!-- <title>Functional Indices</title> -->
  <title>関数インデックス</title>
<indexterm><primary sortas="かんすういんでっくす">関数インデックス</primary></indexterm>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="かんすういんでっくす">関数インデックス</secondary></indexterm>
  <para>
   <!-- For a <firstterm>functional index</firstterm>, an index is defined
   on the result of a function applied to one or more columns of a
   single table.  Functional indices can be used to obtain fast access
   to data based on the result of function calls. -->
   <firstterm>関数インデックス</firstterm>では、インデックスは、1つのテーブルの1つ以上のカラムに適用された関数の結果上で定義されます。関数インデックスは、関数呼び出しの結果に基づくデータへの速いアクセスを得るために使うことができます。

  </para>

  <para>
   <!-- For example, a common way to do case-insensitive comparisons is to
   use the <function>lower</function>: -->
   たとえば、大文字/小文字を関係なく比較をするための一般的な方法では、<function>lower</function>関数を使います。</para>

<programlisting>
SELECT * FROM test1 WHERE lower(col1) = 'value';
</programlisting>
   <!-- In order for that query to be able to use an index, it has to be
   defined on the result of the <literal>lower(column)</literal>
   operation: -->

<para>この問い合わせでインデックスを使用するには、インデックスが<literal>lower(column)</literal>演算の結果で定義されている必要があります。</para>

<programlisting>
CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));
</programlisting>

  <para>
   <!-- The function in the index definition can take more than one
   argument, but they must be table columns, not constants.
   Functional indices are always single-column (namely, the function
   result) even if the function uses more than one input field; there
   cannot be multi-column indices that contain function calls. -->

   インデックス定義の関数は1つ以上の引数を取ることができますが、定数ではなくテーブルカラムでなくてはいけません。関数インデックスは、もしその関数が1つ以上の入力フィールドを使うとしても常にシングルカラム（すなわち関数の結果）です。関数呼び出しを含むマルチカラムインデックスはありえないのです。

  </para>

  <tip>
   <para>
    <!-- The restrictions mentioned in the previous paragraph can easily be
    worked around by defining custom functions to use in the index
    definition that call the desired function(s) internally. -->

    しかし、この制約は、求められる関数を内部的に呼び出すインデックス定義の中で使うカスタム関数を定義することで簡単に回避することができます。

   </para>
  </tip>
 </sect1>


 <sect1 id="indices-opclass">
  <!-- <title>Operator Classes</title> -->
  <title>演算子クラス</title>
<indexterm><primary sortas="えんざんしくらす">演算子クラス</primary></indexterm>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="えんざんしくらす">演算子クラス</secondary></indexterm>
  <para>
   <!-- An index definition may specify an <firstterm>operator
   class</firstterm> for each column of an index. -->

   インデックス定義はインデックスのそれぞれのカラムに<firstterm>演算子クラス</firstterm>を指定することができます。
</para>

<synopsis>
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <replaceable>opclass</replaceable> <optional>, ...</optional>);
</synopsis>


<para>
   <!-- The operator class identifies the operators to be used by the index
   for that column.  For example, a B-tree index on four-byte integers
   would use the <literal>int4_ops</literal> class; this operator
   class includes comparison functions for four-byte integers.  In
   practice the default operator class for the column's data type is
   usually sufficient.  The main point of having operator classes is
   that for some data types, there could be more than one meaningful
   ordering.  For example, we might want to sort a complex-number data
   type either by absolute value or by real part.  We could do this by
   defining two operator classes for the data type and then selecting
   the proper class when making an index.  There are also some
   operator classes with special purposes: -->

   演算子クラスは、インデックスがそのカラムのために使う演算子を特定します。たとえば、4バイトの整数のB-treeインデックスは<literal>int4_ops</literal>を使います。この演算子クラスは4バイト整数の比較関数を含んでいます。実際には、カラムのデータ型のデフォルト演算子クラスで普通は十分です。演算子クラスを持つことの大きな意味は、いくつかのデータ型には1つ以上の意味のある順番があり得るということです。たとえば、複素数データ型を絶対値か実数部でソートしたいということがあるかもしれません。これはデータ型の2つの演算子クラスを定義し、インデックスを作るときに適切なクラスを選択することで可能です。ほかにも、特別な目的のための演算子クラスがいくつかあります。</para>


   <itemizedlist>
    <listitem>
     <para>
      <!-- The operator classes <literal>box_ops</literal> and
      <literal>bigbox_ops</literal> both support R-tree indices on the
      <literal>box</literal> data type.  The difference between them is
      that <literal>bigbox_ops</literal> scales box coordinates down,
      to avoid floating point exceptions from doing multiplication,
      addition, and subtraction on very large floating point
      coordinates.  If the field on which your rectangles lie is about
      20 000 units square or larger, you should use
      <literal>bigbox_ops</literal>. -->

      演算子クラス<literal>box_ops</literal>と<literal>bigbox_ops</literal>は、両方ともR-treeインデックスを<literal>box</literal>データ型でサポートしています。これらの違いは、<literal>bigbox_ops</literal>は浮動小数点の例外が非常に大きな浮動小数点の座標で積算、加算、減算の際に発生することを回避するために、ボックス座標を縮小するという点です。もし矩形があるフィールドが20,000ユニット平方かそれ以上の場合は、<literal>bigbox_ops</literal>を使うべきでしょう。
     </para>
    </listitem>
   </itemizedlist>

  <para>
   <!-- The following query shows all defined operator classes: -->
   次の問い合わせは、すべての定義された演算子クラスを表わしています。</para>

<programlisting>
SELECT am.amname AS acc_name,
       opc.opcname AS ops_name,
       opr.oprname AS ops_comp
    FROM pg_am am, pg_amop amop,
         pg_opclass opc, pg_operator opr
    WHERE amop.amopid = am.oid AND
          amop.amopclaid = opc.oid AND
          amop.amopopr = opr.oid
    ORDER BY acc_name, ops_name, ops_comp;
</programlisting>
 </sect1>


  <sect1 id="keys">
   <!-- <title id="keys-title">Keys</title> -->
   <title id="keys-title">キー</title>
<indexterm><primary sortas="きー">キー</primary></indexterm>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="きー">キー</secondary></indexterm>
    <note>
     <!-- <title>Author</title> -->
     <title>著者</title>
     <para>
      <!-- Written by Herouth Maoz (<email>herouth@oumail.openu.ac.il</email>).
      This originally appeared on the User's Mailing List on 1998-03-02
      in response to the question:
      "What is the difference between PRIMARY KEY and UNIQUE constraints?". -->

      Herouth Maoz（<email>herouth@oumail.openu.ac.il</email>）によって書かれました。もともとは1998年3月2日のユーザーメーリングリストで「PRIMARY KEYとUNIQUE制約の違いは何ですか？」という、以下のような質問の答えとして現われました。
     </para>
    </note>

   <formalpara>
<!--<literallayout>-->
<title>Subject: Re: [QUESTIONS] PRIMARY KEY | UNIQUE</title>

<!--         What's the difference between:

              PRIMARY KEY(fields,...) and
              UNIQUE (fields,...)

       - Is this an alias?
       - If PRIMARY KEY is already unique, then why
         is there another kind of key named UNIQUE? -->

<para>
PRIMARY KEY(fields,...)とUNIQUE (fields,...)の違いは何ですか？

<itemizedlist>
<listitem><para>これは別名ですか?</para></listitem>
<listitem><para>もしPRIMARY KEYがすでに一意ならば、なぜUNIQUEと呼ばれる別のキーがあるのですか?</para></listitem>
</itemizedlist>
</para>
<!--</literallayout>-->
   </formalpara>

   <para>
    <!-- A primary key is the field(s) used to identify a specific row. 
    For example,
    Social Security numbers identifying a person. -->

    主キー（primary key）は、特定の行を認別するためのフィールドです。たとえば、ある人を識別するためには社会保障番号があります。

   </para>

   <para>
    <!-- A simply UNIQUE combination of fields has nothing to do with 
    identifying
    the row. It's simply an integrity constraint. For example, I have
    collections of links. Each collection is identified by a unique number,
    which is the primary key. This key is used in relations. -->

    単純にUNIQUEである組み合わせのフィールドは、行の特定とは関係ありません。それは単に整合性制約なのです。たとえば、複数のリンク集合を持っているとします。それぞれの集合は一意な数字で特定され、それが主キーとよばれます。このキーはリレーションで使われます。

   </para>

   <para>
   <!-- 
    However, my application requires that each collection will also have a
    unique name. Why? So that a human being who wants to modify a collection
    will be able to identify it. It's much harder to know, if you have two
    collections named <quote>Life Science</quote>, the the one tagged 24433 
    is the one you
    need, and the one tagged 29882 is not. -->

    しかし、アプリケーションはそれぞれの集合が一意な名前も持つことを要求します。なぜでしょうか？ それは、集合を修正する人間が識別できるからです。もし<quote>生命科学</quote>と呼ばれる集合が2つあり、29882ではなく24433という番号の付けられた方が必要だという場合、非常にわかりにくくなってしまいます。

   </para>

   <para>
    <!-- So, the user selects the collection by its name. We therefore 
    make sure,
    within the database, that names are unique. However, no other table in the
    database relates to the collections table by the collection Name. That
    would be very inefficient. -->

    ですから、ユーザーは集合を名前で選択します。したがって、データベースの中で名前は一意であることを確認しなければいけません。しかし、データベースの中で、集合の名前から集合テーブルに関係するものはありません。それはあまり効率がよくありません。

   </para>

   <para>
    <!-- Moreover, despite being unique, the collection name does not actually
    define the collection! For example, if somebody decided to change the name
    of the collection from <quote>Life Science</quote> to <quote>Biology</quote>, it will still be the
    same collection, only with a different name. As long as the name is unique,
    that's OK. -->

    さらに、一意であるにもかかわらず、集合名は実際に集合を定義するわけではありません。たとえば、もし誰かが<quote>生命科学</quote>を<quote>生物学</quote>に変えようとしても、それは名前だけが違う同じ集合のままです。名前が一意である限りはそれで大丈夫です。

   </para>

   <para>
    <!-- So: -->
    ですから、以下のようなことがいえます。
</para>

    <itemizedlist>
     <listitem>
      <para>
       <!-- Primary key: -->
       主キーは以下のような性質を持ちます。</para>
       <itemizedlist spacing="compact" mark="bullet">
	<listitem>
	 <para>
	  <!-- Is used for identifying the row and relating to it. -->
          行を識別し関連するために使われます。
	 </para>
	</listitem>
	<listitem>
	 <para>
	  <!-- Is impossible (or hard) to update. -->
          更新は不可能（もしくは難しい）です。
	</para>
	</listitem>
	<listitem>
	<para>
	  <!-- Should not allow NULLs. -->
          NULLを許しません。
	</para>
	</listitem>
       </itemizedlist>
     </listitem>

     <listitem>
      <para>
       <!-- Unique field(s): -->
       一意なフィールドは以下のような性質を持ちます。</para>
       <itemizedlist spacing="compact" mark="bullet">
	<listitem>
	<para>
	  <!-- Are used as an alternative access to the row. -->
          行列への代替アクセスとして使われます。
	</para>
	</listitem>
	<listitem>
	<para>
	  <!-- Are updatable, so long as they are kept unique. -->
          一意であり続ければ、更新が可能です。
	</para>
	</listitem>
	<listitem>
	<para>
	  <!-- NULLs are acceptable. -->
          NULLが可能です。
	</para>
	</listitem>
       </itemizedlist>
     </listitem>
    </itemizedlist>

   <para>
    <!-- As for why no non-unique keys are defined explicitly in standard
    <acronym>SQL</acronym> syntax? Well, you
    must understand that indices are implementation-dependent.
    <acronym>SQL</acronym> does not
    define the implementation, merely the relations between data in the
    database. <productname>Postgres</productname> does allow
    non-unique indices, but indices
    used to enforce <acronym>SQL</acronym> keys are always unique. -->

    なぜ標準<acronym>SQL</acronym>構文では非一意なキーが明白に定義されているのでしょう？ まず、インデックスは実装に依存するということを理解しなければいけません。<acronym>SQL</acronym>は実装を定義するのではなく、単にデータベースのデータ中にあるリレーションのみを定義します。<productname>Postgres</productname>は非一意なインデックスを認めませんが、<acronym>SQL</acronym>キーを強制するために使われるインデックスは常に一意です。

   </para>

   <para>
    <!-- Thus, you may query a table by any combination of its columns, 
    despite the
    fact that you don't have an index on these columns. The indexes are merely
    an implementation aid that each <acronym>RDBMS</acronym> offers
    you, in order to cause
    commonly used queries to be done more efficiently.
    Some <acronym>RDBMS</acronym> may give you
    additional measures, such as keeping a key stored in main memory. They will
    have a special command, for example  -->

   したがって、カラムにインデックスがないにもかかわらず、そのカラムのどんな組み合わせでもテーブルを問い合わせることができます。そのインデックスは単に、一般的に使われる問い合わせをより効率よく行うために<acronym>RDBMS</acronym>が提供する実装の手助けです。いくつかの<acronym>RDBMS</acronym>は、キーをメインメモリに残すなどの付加を与えます。それらは、たとえば以下のような特別なコマンドを持っています（これは実際にあるコマンドではなく、ただの例です）。
</para>


<synopsis>
CREATE MEMSTORE ON <replaceable>table</replaceable> COLUMNS <replaceable>cols</replaceable>
</synopsis>
    <!-- (This is not an existing command, just an example.) -->

   <para>
    <!-- In fact, when you create a primary key or a unique combination of 
    fields,
    nowhere in the <acronym>SQL</acronym> specification does it say
    that an index is created, nor that
    the retrieval of data by the key is going to be more efficient than a
    sequential scan! -->

    実際、主キーもしくはフィールドの一意な組み合わせを作る場合、<acronym>SQL</acronym>規格のどこでもインデックスが作られたことやキーによるデータの抽出が順スキャンよりも効率がよくなるとは言っていません!
       </para>

   <para>
    <!-- So, if you want to use a combination of fields that is not unique as a
    secondary key, you really don't have to specify anything - just start
    retrieving by that combination! However, if you want to make the retrieval
    efficient, you'll have to resort to the means your
    <acronym>RDBMS</acronym> provider gives you
    - be it an index, my imaginary MEMSTORE command, or an intelligent
    <acronym>RDBMS</acronym>
    that creates indices without your knowledge based on the fact that you have
    sent it many queries based on a specific combination of keys... (It learns
    from experience). -->

    ですから、もし一意ではないフィールドの組み合わせを二次キーとして使いたい場合、何も指定する必要がありません。ただその組み合わせで抽出を始めるだけです。しかし、もし抽出を効率よく行いたい場合は、使っている<acronym>RDBMS</acronym>プロバイダが提供する方法に頼らなくてはいけません。たとえばインデックスや、空想上のMEMSTOREコマンドや、指定されたキーのコンビネーションに基づいたたくさんの問い合わせを送ったという事実に基づいて知らないうちにインデックスを作る賢い<acronym>RDBMS</acronym>かもしれません（それは経験から学ぶことができるのです）。
   </para>
  </sect1>


  <sect1 id="partial-index">
   <title id="partial-index-title"><!--Partial Indices-->部分インデックス</title>
<indexterm><primary sortas="ぶぶんいんでっくす">部分インデックス</primary></indexterm>
<indexterm><primary sortas="いんでっくす">インデックス</primary><secondary sortas="ぶぶんいんでっくす">部分インデックス</secondary></indexterm>
   <note>
    <!-- <title>Author</title> -->
    <title>著者</title>
    <para>
     <!-- This is from a reply to a question on the email list
     by Paul M. Aoki (<email>aoki@CS.Berkeley.EDU</email>)
     on 1998-08-11. -->

     これはPaul M. Aoki（<email>aoki@CS.Berkeley.EDU</email>）による、メーリングリストで投稿された質問に対する返答の情報をもとに記述されています。

<!--
  Paul M. Aoki         | University of California at Berkeley
  aoki@CS.Berkeley.EDU | Dept. of EECS, Computer Science Division #1776
                       | Berkeley, CA 94720-1776
-->
    </para>
   </note>

   <note>
    <!-- <title>Note</title> -->
    <title>注釈</title>
    <para>
     <!-- Partial indices are not currently supported by
     <productname>PostgreSQL</productname>, but they were once supported
     by its predecessor <productname>Postgres</productname>, and much
     of the code is still there.  We hope to revive support for this
     feature someday. -->

     部分インデックスは、現在のところ<productname>PostgreSQL</productname>ではサポートされていませんが、前身である<productname>Postgres</productname>ではサポートされていたことがあり、コードのうちの多くがまだ残っています。この機能のサポートはいつか復活させたいと思っています。

    </para>
   </note>

   <para>
    <!-- A <firstterm>partial index</firstterm>
    is an index built over a subset of a table; the subset is defined by
    a predicate.  <productname>Postgres</productname>
    supported partial indices with arbitrary
    predicates.  I believe IBM's <productname>DB2</productname>
    for AS/400 supports partial indices
    using single-clause predicates. -->

    <firstterm>部分インデックス</firstterm>はテーブルのサブセットに構築されるインデックスで、そのサブセットは述語によって定義されます。<productname>Postgres</productname>は、任意の述語で部分インデックスをサポートしていました。たしか、IBMのAS/400用の<productname>DB2</productname>は、単独句述語を使って部分インデックスをサポートしていたと思います。

   </para>

   <para>
    <!-- The main motivation for partial indices is this:
    if all of the queries you ask that can
    profitably use an index fall into a certain range, why build an index
    over the whole table and suffer the associated space/time costs?

    (There are other reasons too; see 
    <xref endterm="STON89b" linkend="STON89b-full"> for details.) -->

    部分インデックスの重要な動機は以下のとおりです。「もしインデックスを有効に使うことのできるすべての自分が行う問い合わせが一定の値にあるならば、なぜテーブル全体にインデックスを付け、空間/時間のコストに苦しまなければいけないのでしょうか?」

   </para>

   <para>
    <!-- The machinery to build, update and query partial indices isn't too
    bad.  The hairy parts are index selection (which indices do I build?)
    and query optimization (which indices do I use?); i.e., the parts
    that involve deciding what predicate(s) match the workload/query in
    some useful way.  For those who are into database theory, the problems
    are basically analogous to the corresponding materialized view
    problems, albeit with different cost parameters and formulae.  These
    are, in the general case, hard problems for the standard ordinal 
    <acronym>SQL</acronym>
    types; they're super-hard problems with black-box extension types,
    because the selectivity estimation technology is so crude. -->

    部分インデックスを構築、更新し、問い合わせる部分はそれほど悪くありません。面倒なのはインデックスの選択（どのインデックスを構築すればよいのでしょう？）そして問い合わせの最適化（どのインデックスを使えばよいのでしょう？）です。つまり、仕事/問い合わせに適しているかを決定する部分などがあります。データベース理論に興味を持っている人のために説明すると、コストパラメータも計算式も違いますが、問題は、基本的に対応する実現化されたビューの問題と類似しています。コストの異なるパラメータや公式で作業することです。これらは一般的な場合に、標準の順序の<acronym>SQL</acronym>型には難しい問題です。そしてブラックボックス拡張型にとってはとても難しい問題です。なぜなら選択性概算の技術がとても粗野だからです。

   </para>

   <para>
    <!-- Check <xref endterm="STON89b" linkend="STON89b-full">,
    <xref endterm="OLSON93" linkend="OLSON93-full">,
    and
    <xref endterm="SESHADRI95" linkend="SESHADRI95-full">
    for more information. -->

    詳しい情報は、<citetitle><xref endterm="STON89b" linkend="STON89b-full"></citetitle>、<citetitle><xref endterm="OLSON93" linkend="OLSON93-full"></citetitle>、<citetitle><xref endterm="SESHADRI95" linkend="SESHADRI95-full"></citetitle>を参照してください。

   </para>
  </sect1>
 </chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode:sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:("/usr/lib/sgml/catalog")
sgml-local-ecat-files:nil
End:
-->
