List:Internals« Previous MessageNext Message »
From:mhillyer Date:June 20 2005 2:27pm
Subject:bk commit - mysqldoc@docsrva tree (Mike.Hillyer:1.2823)
View as plain text  
Below is the list of changes that have just been committed into a local
mysqldoc repository of root. When root does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://www.mysql.com/doc/I/n/Installing_source_tree.html

ChangeSet
  1.2823 05/06/20 08:27:13 Mike.Hillyer@stripped +1 -0
  Work in progress push, I still need to finish the EXPLAIN section when I have a populated sample DB and do proofreading.

  userguide/indexing.xml
    1.4 05/06/20 08:27:13 Mike.Hillyer@stripped +653 -8
    Work in progress push, I still need to finish the EXPLAIN section when I have a populated sample DB and do proofreading.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	Mike.Hillyer
# Host:	www.openwin.org
# Root:	/home/mysqldoc/mysqldoc

--- 1.3/userguide/indexing.xml	2005-06-17 22:07:31 -06:00
+++ 1.4/userguide/indexing.xml	2005-06-20 08:27:13 -06:00
@@ -781,8 +781,8 @@
   <title>Creating and Using Composite Indexes</title>
 
   <para>
-   When executing a <literal>SELECT</literal> query, MySQL only uses one
-   index per table involved in the query. If the
+   When executing a <literal>SELECT</literal> query, MySQL typically
+   uses only one index per table involved in the query. If the
    <literal>WHERE</literal> clause of the query references more than one
    column, a single-column index may be less than optimal. For example,
    say you were executing the following query:
@@ -879,7 +879,10 @@
 
   <title>Dropping Indexes</title>
 
-  <para>Existing indexes can be dropped using either a <literal>DROP INDEX</literal> or <literal>ALTER TABLE</literal> syntax:</para>
+  <para>
+   Existing indexes can be dropped using either a <literal>DROP
+   INDEX</literal> or <literal>ALTER TABLE</literal> syntax:
+  </para>
 
 <programlisting>
  DROP INDEX <replaceable>index_name</replaceable> ON <replaceable>table_name</replaceable>
@@ -887,13 +890,15 @@
 ALTER TABLE <replaceable>table_name</replaceable> DROP INDEX <replaceable>index_name</replaceable>
 </programlisting>
 
-<para>
- You can drop multiple indexes in a single <literal>ALTER TABLE</literal> statement by separating them with commas:
-</para>
+  <para>
+   You can drop multiple indexes in a single <literal>ALTER
+   TABLE</literal> statement by separating them with commas:
+  </para>
 
 <programlisting>
  ALTER TABLE actor DROP PRIMARY KEY, DROP INDEX last_first_name
 </programlisting>
+
  </section>
 
 <!-- END DROPPING -->
@@ -902,7 +907,105 @@
 
   <title>Using FULLTEXT Indexes</title>
 
-  <para></para>
+  <para>
+   While regular indexes are effective for many purposes, they are not
+   effective for columns that contain natural language. An index can be
+   used for single word <literal>CHAR</literal> and
+   <literal>VARCHAR</literal> columns, but <literal>FULLTEXT</literal>
+   indexes are designed for finding strings within larger natural
+   language fields.
+  </para>
+
+  <para>
+   A <literal>FULLTEXT</literal> search takes a string and column list
+   and searches the specified columns for the string, returning results
+   ranked by relevancy.
+  </para>
+
+  <para>
+   The <literal>FULLTEXT</literal> index is available for the
+   <literal>MyISAM</literal> storage engine only.
+  </para>
+
+  <para>
+   The syntax for creating a <literal>FULLTEXT</literal> index is listed
+   in <xref linkend="indexing-creating" />. Once the index is created,
+   the <literal>MATCH ... AGAINST</literal> syntax can be used to
+   perform <literal>FULLTEXT</literal> queries.
+  </para>
+
+  <para>
+   The <literal>MATCH</literal> clause indicates which columns are to be
+   searched. The list of columns in the <literal>MATCH</literal> clause
+   must match with the list of columns in the
+   <literal>FULLTEXT</literal> index.
+  </para>
+
+  <para>
+   The <literal>AGAINST</literal> clause contains the string being
+   searched for. The string in the <literal>AGAINST</literal> clause
+   must be a constant string: you cannot use a user variable or search
+   result in the <literal>AGAINST</literal> clause.
+  </para>
+
+  <para>
+   Here is an example of a basic <literal>FULLTEXT</literal> query that
+   searches for movies in the <literal>film</literal> table that contain
+   the word <literal>army</literal> in the <literal>title</literal> or
+   <literal>description</literal> columns:
+  </para>
+
+<programlisting>
+ SELECT * FROM army WHERE MATCH (title, description) AGAINST ('army')
+
+UPDATEME: SHOW RESULTS WHEN SAMPLE DB IS FINISHED AND POPULATED
+</programlisting>
+
+  <para>
+   Results from a query with <literal>MATCH ... AGAINST</literal> in the
+   <literal>WHERE</literal> clause will always return in descending
+   order based on relevancy.
+  </para>
+
+  <para>
+   Here is the same query performed with a <literal>LIKE</literal>
+   clause instead:
+  </para>
+
+<programlisting>
+ SELECT * FROM film WHERE title LIKE '%army%' OR description LIKE '%army%'
+</programlisting>
+
+  <para>
+   Note the significant performance inprovement provided by the
+   <literal>FULLTEXT</literal> index.
+  </para>
+
+  <para>
+   The <literal>MATCH ... AGAINST</literal> syntax can also provide
+   relevancy ranking information:
+  </para>
+
+<programlisting>
+ SELECT title, MATCH (title, description) AGAINST ('army') AS rank
+ FROM film
+ WHERE MATCH (title, description) AGAINST ('army')
+
+UPDATEME: FILL IN RESULTS WHEN SAMPLE DB IS POPULATED
+</programlisting>
+
+  <para>
+   The relevancy scores are based on the weighting of words within the
+   individual rows. Words that occur rarely in the table are ranked
+   higher than words that appear in a large percentage of the rows.
+  </para>
+
+  <para>
+   For more information on the <literal>FULLTEXT</literal> search
+   engine, see the
+   <ulink url="http://dev.mysql.com/doc/mysql/en/fulltext-search.html">Fulltext
+   Search</ulink> section of the MySQL Reference Manual.
+  </para>
 
  </section>
 
@@ -912,7 +1015,549 @@
 
   <title>Using EXPLAIN to Optimize Indexing</title>
 
-  <para></para>
+  <para>
+   Sometimes it is not easy to identify which columns of a table to
+   index, even when you have identified the slow queries in your
+   application. The <literal>EXPLAIN</literal> statement is designed to
+   assist in the query optimization process by providing insight into
+   how the MySQL optimizer handles a specific query.
+  </para>
+
+  <para>
+   To analyze a query, precede the query with the
+   <literal>EXPLAIN</literal> keyword:
+  </para>
+
+<programlisting>
+ EXPLAIN SELECT something UPDATEME FILL THIS IN
+</programlisting>
+
+  <para>
+   <literal>EXPLAIN</literal> returns a row of information for each
+   table used in the <literal>SELECT</literal> statement. The tables are
+   listed in the output in the order that MySQL would read them while
+   processing the query.
+  </para>
+
+  <para>
+   Each output row from <literal>EXPLAIN</literal> provides information
+   about one table, and each row consists of the following columns:
+  </para>
+
+  <itemizedlist>
+
+   <listitem><para>
+    <literal>id</literal>
+   </para>
+
+   <para>
+    The <literal>SELECT</literal> identifier. This is the sequential
+    number of the <literal>SELECT</literal> within the query. The
+    <literal>id</literal> is not used when optimizing queries.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>select_type</literal>
+   </para>
+
+   <para>
+    The type of <literal>SELECT</literal>, which can be any of the
+    following:
+   </para>
+
+   <itemizedlist>
+
+    <listitem><para>
+     <literal>SIMPLE</literal>: Simple <literal>SELECT</literal> query
+     (not using <literal>UNION</literal> or subqueries).
+    </para></listitem>
+
+    <listitem><para>
+     <literal>PRIMARY</literal>: Outermost <literal>SELECT</literal>
+     query.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>UNION</literal>: Second or later <literal>SELECT</literal>
+     statement in a <literal>UNION</literal> query.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>DEPENDENT UNION</literal>: Second or later
+     <literal>SELECT</literal> statement in a <literal>UNION</literal>,
+     dependent on outer query.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>UNION RESULT</literal>: Result of a
+     <literal>UNION</literal> query.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>SUBQUERY</literal>: First <literal>SELECT</literal> in
+     subquery.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>DEPENDENT SUBQUERY</literal>: First
+     <literal>SELECT</literal> in subquery, dependent on outer query.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>DERIVED</literal>: Derived table <literal>SELECT</literal>
+     (subquery in <literal>FROM</literal> clause).
+    </para></listitem>
+
+   </itemizedlist>
+
+   <para>
+    The <literal>select_type</literal> value is useful in identifying
+    which portion of the source query the table in question is used for,
+    but is not the focus of query optimization.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>table</literal>
+   </para>
+
+   <para>
+    The table to which the row of output refers.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>type</literal>
+   </para>
+
+   <para>
+    The join type. The different join types are listed here, ordered
+    from the best type to the worst:
+   </para>
+
+   <itemizedlist>
+
+    <listitem><para>
+     <literal>system</literal>: The table has only one row (i.e. system
+     table). This type will not often be encountered.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>const</literal>: The table has at most one matching row,
+     which is read at the start of the query. Because there is only one
+     row, values from the column in this row can be regarded as
+     constants by optimizer. <literal>const</literal> tables are very
+     fast because they are read only once.
+    </para>
+
+    <para>
+     <literal>const</literal> is used when you compare all parts of a
+     <literal>PRIMARY KEY</literal> or <literal>UNIQUE</literal> index
+     with constant values. The tables in these queries would be classed
+     as <literal>const</literal> because the columns in the where clause
+     either are the primary key or form all parts of the primary key:
+    </para>
+
+    <para>
+<programlisting>
+SELECT * FROM <replaceable>film</replaceable> WHERE <replaceable>film_id</replaceable>=1
+
+SELECT * FROM <replaceable>film_actor</replaceable>
+WHERE <replaceable>film_id</replaceable>=1 AND <replaceable>actor_id</replaceable>=2
+</programlisting>
+    </para></listitem>
+
+    <listitem><para>
+     <literal>eq_ref</literal>: One row is read from this table for each
+     combination of rows from the previous tables. Other than the
+     <literal>const</literal> types, this is the best possible join
+     type. It is used when all parts of an index are used by the join
+     and the index is a <literal>PRIMARY KEY</literal> or
+     <literal>UNIQUE</literal> index.
+    </para>
+
+    <para>
+     <literal>eq_ref</literal> can be used for indexed columns that are
+     compared using the <literal>=</literal> operator. The comparison
+     value can be a constant or an expression that uses columns from
+     tables that are read before this table.
+    </para>
+
+    <para>
+     In the following example, MySQL can use an
+     <literal>eq_ref</literal> join to process the
+     <literal>category</literal> table because the
+     <literal>category_id</literal> column of the
+     <literal>category</literal> table is the primary key and therefore
+     there is only one matching row in the <literal>category</literal>
+     table for each row in the <literal>film</literal> table:
+    </para>
+
+<programlisting>
+SELECT film.title, category.name 
+FROM film, catgeory
+WHERE film.category_id = category.category_id
+</programlisting></listitem>
+
+    <listitem><para>
+     <literal>ref</literal>: All rows with matching index values are
+     read from this table for each combination of rows from the previous
+     tables. <literal>ref</literal> is used if the join uses only part
+     of a <literal>PRIMARY KEY</literal> or <literal>UNIQUE</literal>
+     index of if the index does not enforce uniquness (in other words,
+     if the join cannot select a single row based on the key value). If
+     the key that is used matches only a few rows, this is a good join
+     type.
+    </para>
+
+    <para>
+     <literal>ref</literal> can be used for indexed columns that are
+     compared using the <literal>=</literal> or
+     <literal>&lt;=&gt;</literal> operator.
+    </para>
+
+    <para>
+     In the following example, MySQL can use a <literal>ref</literal>
+     join to process the <literal>inventory</literal> table because
+     there is a non-unique index on the <literal>film_id</literal>
+     column of the <literal>inventory</literal> table:
+    </para>
+
+    <para>
+<programlisting>
+SELECT film.title, inventory.inventory_id
+FROM film, inventory
+WHERE inventory.film_id = film.film_id
+</programlisting>
+    </para></listitem>
+
+    <listitem><para>
+     <literal>ref_or_null</literal>: This join type is like
+     <literal>ref</literal>, but with the addition that MySQL does an
+     extra search for rows that contain <literal>NULL</literal> values.
+     This join type is mostly used when resolving subqueries.
+    </para>
+
+    <para>
+     In the following examples, MySQL can use a
+     <literal>ref_or_null</literal> join to process
+     <replaceable>ref_table</replaceable>:
+    </para>
+
+    <remark>
+     [MH] UPDATEME FIND A QUERY FOR THE SAMPDB THAT CAUSES A ref_or_null
+    </remark>
+
+    <para>
+<programlisting>
+SELECT * FROM <replaceable>ref_table</replaceable>
+WHERE <replaceable>key_column</replaceable>=<replaceable>expr</replaceable> OR <replaceable>key_column</replaceable> IS NULL;
+</programlisting>
+    </para></listitem>
+
+    <listitem><para>
+     <literal>index_merge</literal>: This join type indicates that an
+     Index Merge optimization is used to reference multiple indexes. In
+     this case, the <literal>key</literal> column contains a list of
+     indexes used, and <literal>key_len</literal> contains a list of the
+     longest key parts for the indexes used. For more information, see
+     the
+     <ulink url="http://dev.mysql.com/doc/mysql/en/index-merge-optimization.html">Index
+     Merge Optimization</ulink> section of the MySQL Reference Manual.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>unique_subquery</literal>: This type replaces
+     <literal>ref</literal> for some <literal>IN</literal> subqueries of
+     the following form:
+
+<programlisting>
+<replaceable>value</replaceable> IN (SELECT <replaceable>primary_key</replaceable> FROM <replaceable>single_table</replaceable> WHERE <replaceable>some_expr</replaceable>)
+</programlisting>
+
+     <literal>unique_subquery</literal> is just an index lookup function
+     that replaces the subquery completely for better efficiency.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>index_subquery</literal>
+    </para>
+
+    <para>
+     This join type is similar to <literal>unique_subquery</literal>. It
+     replaces <literal>IN</literal> subqueries, but it works for
+     non-unique indexes in subqueries of the following form:
+    </para>
+
+    <para>
+<programlisting>
+<replaceable>value</replaceable> IN (SELECT <replaceable>key_column</replaceable> FROM <replaceable>single_table</replaceable> WHERE <replaceable>some_expr</replaceable>)
+</programlisting>
+    </para></listitem>
+
+    <listitem><para>
+     <literal>range</literal>: Only rows that are in a given range are
+     retrieved, using an index to select the rows. The
+     <literal>key</literal> column indicates which index is used. The
+     <literal>key_len</literal> contains the longest key part that was
+     used. The <literal>ref</literal> column is <literal>NULL</literal>
+     for this type.
+    </para>
+
+    <para>
+     <literal>range</literal> can be used for when a key column is
+     compared to a constant using any of the <literal>=</literal>,
+     <literal>&lt;&gt;</literal>, <literal>&gt;</literal>,
+     <literal>&gt;=</literal>, <literal>&lt;</literal>,
+     <literal>&lt;=</literal>, <literal>IS NULL</literal>,
+     <literal>&lt;=&gt;</literal>, <literal>BETWEEN</literal>, or
+     <literal>IN</literal> operators:
+    </para>
+
+    <para>
+<programlisting>
+SELECT * FROM <replaceable>tbl_name</replaceable>
+WHERE <replaceable>key_column</replaceable> = 10;
+
+SELECT * FROM <replaceable>tbl_name</replaceable>
+WHERE <replaceable>key_column</replaceable> BETWEEN 10 and 20;
+
+SELECT * FROM <replaceable>tbl_name</replaceable>
+WHERE <replaceable>key_column</replaceable> IN (10,20,30);
+
+SELECT * FROM <replaceable>tbl_name</replaceable>
+WHERE <replaceable>key_part1</replaceable>= 10 AND <replaceable>key_part2</replaceable> IN (10,20,30);
+</programlisting>
+    </para></listitem>
+
+    <listitem><para>
+     <literal>index</literal>: This join type is the same as
+     <literal>ALL</literal>, except that only the index tree is scanned.
+     This usually is faster than <literal>ALL</literal>, because the
+     index file usually is smaller than the data file.
+    </para>
+
+    <para>
+     MySQL can use this join type when the query uses only columns that
+     are part of a single index.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>ALL</literal>: A full table scan is done for each
+     combination of rows from the previous tables. This is normally not
+     good if the table is the first table not marked
+     <literal>const</literal>, and usually <emphasis>very</emphasis> bad
+     in all other cases. Normally, you can avoid <literal>ALL</literal>
+     by adding indexes that allow row retrieval from the table based on
+     constant values or column values from earlier tables.
+    </para></listitem>
+
+   </itemizedlist></listitem>
+
+   <listitem><para>
+    <literal>possible_keys</literal>
+   </para>
+
+   <para>
+    The <literal>possible_keys</literal> column indicates which indexes
+    MySQL could use to find the rows in this table. This column is
+    totally independent of the order of the tables as displayed in the
+    output from <literal>EXPLAIN</literal>. That means that some of the
+    keys in <literal>possible_keys</literal> might not be usable in
+    practice with the generated table order.
+   </para>
+
+   <para>
+    If this column is <literal>NULL</literal>, there are no relevant
+    indexes. In this case, you may be able to improve the performance of
+    your query by examining the <literal>WHERE</literal> clause to see
+    whether it refers to some column or columns that would be suitable
+    for indexing. If so, create an appropriate index and check the query
+    with <literal>EXPLAIN</literal> again.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>key</literal>
+   </para>
+
+   <para>
+    The <literal>key</literal> column indicates the key (index) that
+    MySQL actually decided to use. The key is <literal>NULL</literal> if
+    no index was chosen.
+   </para>
+
+   <para>
+    For <literal>MyISAM</literal> tables, running <literal>ANALYZE
+    TABLE</literal> helps the optimizer choose better indexes.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>key_len</literal>
+   </para>
+
+   <para>
+    The <literal>key_len</literal> column indicates the length of the
+    key that MySQL decided to use. The value of
+    <literal>key_len</literal> allows you to determine how many parts of
+    a multiple-part key MySQL actually uses.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>ref</literal>
+   </para>
+
+   <para>
+    The <literal>ref</literal> column shows which columns or constants
+    are used with the <literal>key</literal> to select rows from the
+    table.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>rows</literal>
+   </para>
+
+   <para>
+    The <literal>rows</literal> column indicates the number of rows
+    MySQL believes it must examine to execute the query.
+   </para></listitem>
+
+   <listitem><para>
+    <literal>Extra</literal>
+   </para>
+
+   <para>
+    This column contains additional information about how MySQL resolves
+    the query. Here is an explanation of the different text strings that
+    can appear in this column:
+   </para>
+
+   <itemizedlist>
+
+    <listitem><para>
+     <literal>Distinct</literal>: MySQL stops searching for more rows
+     for the current row combination after it has found the first
+     matching row.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>Not exists</literal>: MySQL was able to do a <literal>LEFT
+     JOIN</literal> optimization on the query and does not examine more
+     rows in this table for the previous row combination after it finds
+     one row that matches the <literal>LEFT JOIN</literal> criteria.
+    </para>
+
+    <para>
+     Here is an example of the type of query that can be optimized this
+     way:
+    </para>
+
+    <para>
+<programlisting>
+SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id
+WHERE t2.id IS NULL;
+</programlisting>
+    </para>
+
+    <para>
+     Assume that <literal>t2.id</literal> is defined as <literal>NOT
+     NULL</literal>. In this case, MySQL scans <literal>t1</literal> and
+     looks up the rows in <literal>t2</literal> using the values of
+     <literal>t1.id</literal>. If MySQL finds a matching row in
+     <literal>t2</literal>, it knows that <literal>t2.id</literal> can
+     never be <literal>NULL</literal>, and does not scan through the
+     rest of the rows in <literal>t2</literal> that have the same
+     <literal>id</literal> value. In other words, for each row in
+     <literal>t1</literal>, MySQL needs to do only a single lookup in
+     <literal>t2</literal>, regardless of how many rows actually match
+     in <literal>t2</literal>.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>range checked for each record (index map: #)</literal>:
+     MySQL found no good index to use, but found that some of indexes
+     might be used once column values from preceding tables are known.
+     For each row combination in the preceding tables, MySQL checks
+     whether it is possible to use a <literal>range</literal> or
+     <literal>index_merge</literal> access method to retrieve rows.
+    </para>
+
+    <para>
+     This is not very fast, but is faster than performing a join with no
+     index at all.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>Using filesort</literal>: MySQL needs to do an extra pass
+     to find out how to retrieve the rows in sorted order. The sort is
+     done by going through all rows according to the join type and
+     storing the sort key and pointer to the row for all rows that match
+     the <literal>WHERE</literal> clause. The keys then are sorted and
+     the rows are retrieved in sorted order.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>Using index</literal>: The column information is retrieved
+     from the table using only information in the index tree without
+     having to do an additional seek to read the actual row. This
+     strategy can be used when the query uses only columns that are part
+     of a single index.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>Using temporary</literal>: To resolve the query, MySQL
+     needs to create a temporary table to hold the result. This
+     typically happens if the query contains <literal>GROUP BY</literal>
+     and <literal>ORDER BY</literal> clauses that list columns
+     differently.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>Using where</literal>: A <literal>WHERE</literal> clause
+     is used to restrict which rows to match against the next table or
+     send to the client. Unless you specifically intend to fetch or
+     examine all rows from the table, you may have something wrong in
+     your query if the <literal>Extra</literal> value is not
+     <literal>Using where</literal> and the table join type is
+     <literal>ALL</literal> or <literal>index</literal>.
+    </para>
+
+    <para>
+     If you want to make your queries as fast as possible, you should
+     look out for <literal>Extra</literal> values of <literal>Using
+     filesort</literal> and <literal>Using temporary</literal>.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>Using sort_union(...)</literal> , <literal>Using
+     union(...)</literal> , <literal>Using intersect(...)</literal>:
+     These indicate how index scans are merged for the
+     <literal>index_merge</literal> join type.
+    </para></listitem>
+
+    <listitem><para>
+     <literal>Using index for group-by</literal>: Similar to the
+     <literal>Using index</literal> way of accessing a table,
+     <literal>Using index for group-by</literal> indicates that MySQL
+     found an index that can be used to retrieve all columns of a
+     <literal>GROUP BY</literal> or <literal>DISTINCT</literal> query
+     without any extra disk access to the actual table. Additionally,
+     the index is used in the most efficient way so that for each group,
+     only a few index entries are read.
+    </para></listitem>
+
+   </itemizedlist></listitem>
+
+  </itemizedlist>
+
+  <remark>
+   [MH] NEED TO ADD AN EXAMPLE OF OPTIMIZING A QUERY, FROM THE SAMPLE DB
+   IF POSSIBLE.
+  </remark>
+
+  <para>
+   For additional information on using the <literal>EXPLAIN</literal>
+   statement, see the
+   <ulink url="http://dev.mysql.com/doc/mysql/en/explain.html"><literal>EXPLAIN</literal></ulink>
+   section of the MySQL Reference Manial.
+  </para>
 
  </section>
 
Thread
bk commit - mysqldoc@docsrva tree (Mike.Hillyer:1.2823)mhillyer20 Jun