Index: trunk/workshop-foss4g/indexing.rst
===================================================================
--- trunk/workshop-foss4g/indexing.rst	(revision 81)
+++ trunk/workshop-foss4g/indexing.rst	(revision 1)
@@ -1,26 +1,26 @@
 .. _indexing:
 
-Partie 14 : L'indexation spatiale
-=================================
+Section 14: Spatial Indexing
+============================
 
-Rapellez-vous que l'indexation spatiale est l'une des trois fonctionnalitÃ©s clÃ©s d'une base de donnÃ©es spatiales. Les index permettent l'utilisation de grandes quantitÃ©s de donnÃ©es dans une base. Sans l'indexation, chaque recherche d'entitÃ© nÃ©cessitera d'accÃ©der sÃ©quentiellement Ã  tous les enregistrements de la base de donnÃ©es. L'indexation accÃ©lÃšre les recherches en organisant les donnÃ©es dans des arbres de recherche qui peuvent Ãªtre parcourus efficacement pour retrouver une entitÃ© particuliÃšre.
+Recall that spatial index is one of the three key features of a spatial database. Indexes are what make using a spatial database for large data sets possible. Without indexing, any search for a feature would require a âsequential scanâ of every record in the database. Indexing speeds up searching by organizing the data into a search tree which can be quickly traversed to find a particular record. 
 
-L'indexation spatiale l'un des plus grands atouts de PostGIS. Dans les exemples prÃ©cÃ©dents, nous avons construit nos jointures spatiales en comparant la totalitÃ© des tables. Ceci peut parfois s'avÃ©rer trÃšs coÃ»teux : rÃ©aliser la jointure de deux tables de 10000 enregistrements sans indexation nÃ©cessitera de comparer 100000000 valeurs, les comparaisons requises ne seront plus que 20000 avec l'indexation.
+Spatial indices are one of the greatest assets of PostGIS.  In the previous example building spatial joins requires comparing whole tables with each other. This can get very costly: joining two tables of 10,000 records each without indexes would require 100,000,000 comparisons; with indexes the cost could be as low as 20,000 comparisons.
 
-Lorsque nous avons chargÃ© la table  ``nyc_census_blocks``, l'outil pgShapeLoader crÃ©e automatiquement un index spatial appelÃ© ``nyc_census_blocks_the_geom_gist``.
+When we loaded the ``nyc_census_blocks`` table, the pgShapeLoader automatically created a spatial index called ``nyc_census_blocks_the_geom_gist``
 
-Pour dÃ©montrer combien il est important d'indexer ses donnÃ©es pour la performance des requÃªtes, essayons de requÃªter notre table ``nyc_census_blocks`` **sans** utiliser notre index.
+To demonstrate how important indexes are for performance, let's search ``nyc_census_blocks`` **without** our spatial index. 
 
-La premiÃšre Ã©tape consiste Ã  supprimer l'index.
+Our first step is to remove the index.
 
 .. code-block:: sql
 
   DROP INDEX nyc_census_blocks_the_geom_gist;
-
+  
 .. note::
 
-   La commande ``DROP INDEX`` supprime un index existant de la base de donnÃ©es. Pour de plus amples informations Ã  ce sujet, consultez la `documentation officielle de PostgreSQL <http://docs.postgresql.fr/9.1/sql-dropindex.html>`_.
-
-Maintenant, regardons le temps d'exÃ©cution dans le coin en bas Ã  droite de l'interface de requÃªtage de pgAdmin, puis lanÃ§ons la commande suivante. Notre requÃªte recherche les blocs de la rue Broad.
+   The ``DROP INDEX`` statement drops an existing index from the database system. For more information, see the PostgreSQL `documentation <http://www.postgresql.org/docs/7.4/interactive/sql-dropindex.html>`_.
+   
+Now, watch the "Timing" meter at the lower right-hand corner of the pgAdmin query window and run the following. Our query searches through every single census block in order to identify the Broad Street entry.
 
 .. code-block:: sql
@@ -31,14 +31,14 @@
   ON ST_Contains(blocks.the_geom, subways.the_geom)
   WHERE subways.name = 'Broad St';
-
+  
 ::
 
-       blkid
+       blkid      
  -----------------
   360610007003006
+  
+The ``nyc_census_blocks`` table is very small (only a few thousand records) so even without an index, the query only takes **55 ms** on my test computer.
 
-La table ``nyc_census_blocks`` est trÃšs petite (seulement quelque milliers d'enregistrements) donc mÃªme sans l'index, la requÃªte prends **55 ms** sur l'ordinateur de test.
-
-Maintenant remettons en place l'index et lanÃ§ons de nouveau la requÃªte.
+Now add the spatial index back in and run the query again. 
 
 .. code-block:: sql
@@ -46,87 +46,87 @@
   CREATE INDEX nyc_census_blocks_the_geom_gist ON nyc_census_blocks USING GIST (the_geom);
 
-.. note:: l'utilisation de la clause ``USING GIST`` spÃ©cifie Ã  PostgreSQL de crÃ©er une structure (GIST) pour cet index. Si vous recevez un message d'erreur ressemblant Ã  ``ERROR: index row requires 11340 bytes, maximum size is 8191`` lors de la crÃ©ation, cela signifie sans doute que vous avez omis la clause ``USING GIST``.
+.. note:: The ``USING GIST`` clause tells PostgreSQL to use the generic index structure (GIST) when building the index.  If you receive an error that looks like ``ERROR: index row requires 11340 bytes, maximum size is 8191`` when creating your index, you have likely neglected to add the ``USING GIST`` clause.
 
-Sur l'ordinateur de test le temps d'exÃ©cution se rÃ©duit Ã  **9 ms**. Plus votre table est grande, plus la diffÃ©rence de temps d'exÃ©cution pour une requÃªte utilisant les index augmentera.
+On my test computer the time drops to **9 ms**. The larger your table, the larger the relative speed improvement of an indexed query will be.
 
-Comment les index spatiaux fonctionnent
----------------------------------------
+How Spatial Indexes Work
+------------------------
 
-Les index des bases de donnÃ©es standards crÃ©ent des arbres hiÃ©rarchiques basÃ©s sur les valeurs des colonnes Ã  indexer. Les index spatiaux sont un peu diffÃ©rents - ils ne sont pas capables d'indexer des entitÃ©s gÃ©omÃ©triques elles-mÃªme mais ils indexent leur Ã©tendues.
+Standard database indexes create a hierarchical tree based on the values of the column being indexed. Spatial indexes are a little different -- they are unable to index the geometric features themselves  and instead index the bounding boxes of the features.
 
 .. image:: ./indexing/bbox.png
 
-Dans la figure ci-dessus, le nombre de lignes qui intersectent l'Ã©toile jaune est *unique*, la ligne rouge. Mais l'Ã©tendue des entitÃ©s qui intersectent la boÃ®te jaune sont *deux*, la boÃ®te rouge et la boÃ®te bleue.
+In the figure above, the number of lines that intersect the yellow star is **one**, the red line. But the bounding boxes of features that intersect the yellow box is **two**, the red and blue ones. 
 
-La maniÃšre dont les bases de donnÃ©es rÃ©pondent de maniÃšre efficace Ã  la question "Quelles lignes intersectent l'Ã©toile jaune ?" correspond premiÃšrement Ã  rÃ©pondre Ã  la question "Quelle Ã©tendue intersecte l'Ã©tendue jaune" en utilisant les index (ce qui est trÃšs rapide) puis Ã  calculer le rÃ©sultat exact de la question "Quelles lignes intersectent l'Ã©toile jaune ?" **seulement en utilisant les entitÃ©s retournÃ©es par le premier test**.
+The way the database efficiently answers the question "what lines intersect the yellow star" is to first answer the question "what boxes intersect the yellow box" using the index (which is very fast) and then do an exact calculation of "what lines intersect the yellow star" **only for those features returned by the first test**. 
 
-Pour de grandes tables, il y a un systÃšme en "deux Ã©tapes" d'Ã©valuation en utilisant dans un premier temps l'approximation Ã  l'aide d'index, puis en rÃ©alisant le test exact sur une quantitÃ© bien moins importante de donnÃ©es ce qui rÃ©duit drastiquement le temps de calcul nÃ©cessaire Ã  cette deuxiÃšme Ã©tape.
+For a large table, this "two pass" system of evaluating the approximate index first, then carrying out an exact test can radically reduce the amount of calculations necessary to answer a query.
 
-PotGIS et Oracle Spatial partage la mÃªme notion d'index structurÃ© sous la forme "d'arbres R" [#RTree]_. Les arbres R classent les donnÃ©es sous forme de rectangles, de sous-rectangles etc. Cette structure d'index gÃšre automatiquement la densitÃ© et la taille des objets.
+Both PostGIS and Oracle Spatial share the same "R-Tree" [#RTree]_ spatial index structure. R-Trees break up data into rectangles, and sub-rectangles, and sub-sub rectangles, etc.  It is a self-tuning index structure that automatically handles variable data density and object size.
 
 .. image:: ./indexing/index-01.png
 
-RequÃªte avec seulement des index
---------------------------------
+Index-Only Queries
+------------------
 
-La plupart des fonctions utilisÃ©es par PostGIS (:command:`ST_Contains`, :command:`ST_Intersects`, :command:`ST_DWithin`, etc) prennent en compte les index automatiquement. Mais certaines fonctions (comme par exemple : :command:`ST_Relate`) ne les utilisent pas.
+Most of the commonly used functions in PostGIS (:command:`ST_Contains`, :command:`ST_Intersects`, :command:`ST_DWithin`, etc) include an index filter automatically. But some functions (e.g., :command:`ST_Relate`) do not include and index filter.
 
-Pour utiliser une recherche par Ã©tendue utilisant les index (et pas de filtres), vous pouvez utiliser l'opÃ©rateur :command:`&&`. Pour les gÃ©omÃ©tries, l'opÃ©rateur :command:`&&` signifie "l'Ã©tendue recouvre ou touche" de la mÃªme maniÃšre que l'opÃ©rateur :command:`=` sur des entiers signifie que les valeurs sont Ã©gales.
+To do a bounding-box search using the index (and no filtering), make use of the :command:`&&` operator. For geometries, the :command:`&&` operator means "bounding boxes overlap or touch" in the same way that for number the :command:`=` operator means "values are the same".
 
-Essayons de comparer une requÃªte avec seulement un index pour la population du quartier 'West Village'. En utilisant la commande :command:`&&` notre requÃªte ressemble Ã  cela :
+Let's compare an index-only query for the population of the 'West Village' to a more exact query. Using :command:`&&` our index-only query looks like the following:
 
 .. code-block:: sql
 
-  SELECT Sum(popn_total)
+  SELECT Sum(popn_total) 
   FROM nyc_neighborhoods neighborhoods
   JOIN nyc_census_blocks blocks
   ON neighborhoods.the_geom && blocks.the_geom
   WHERE neighborhoods.name = 'West Village';
-
+  
 ::
 
   50325
-
-Maintenant essayons la mÃªme requÃªte en utilisant la fonction plus prÃ©cise :command:`ST_Intersects`.
+  
+Now let's do the same query using the more exact :command:`ST_Intersects` function.
 
 .. code-block:: sql
 
-  SELECT Sum(popn_total)
+  SELECT Sum(popn_total) 
   FROM nyc_neighborhoods neighborhoods
   JOIN nyc_census_blocks blocks
   ON ST_Intersects(neighborhoods.the_geom, blocks.the_geom)
   WHERE neighborhoods.name = 'West Village';
-
+  
 ::
 
   27141
 
-Un plus faible nombre de rÃ©sultats ! La premiÃšre requÃªte nous renvoie tous les blocs qui intersectent l'Ã©tendue du quartier, la seconde nous renvoie seulement les blocs qui intersectent le quartier lui-mÃªme.
+A much lower answer! The first query summed up every block that intersected the neighborhood's bounding box; the second query only summed up those blocks that intersected the neighborhood itself.
 
-Analyse
+Analyzing
 ---------
 
-Le planificateur de requÃªte de PostgreSQL choisit intelligemment d'utiliser ou non les index pour rÃ©aliser une requÃªte. Il n'est pas toujours plus rapide d'utiliser un index pour rÃ©aliser une recherche : si la recherche doit renvoyer l'ensemble des enregistrements d'une table, parcourir l'index pour rÃ©cupÃ©rer chaque valeur sera plus lent que de parcourir linÃ©airement l'ensemble de la table.
+The PostgreSQL query planner intelligently chooses when to use or not to use indexes to evaluate a query. Counter-intuitively, it is not always faster to do an index search: if the search is going to return every record in the table, traversing the index tree to get each record will actually be slower than just linearly reading the whole table from the start.
 
-Afin de savoir dans quelle situation il est nÃ©cessaire d'utiliser les index (lire une petite partie de la table plutÃŽt qu'une grande partie), PostgreSQL conserve des statistiques relatives Ã  la distribution des donnÃ©es dans chaque colonne indexÃ©e. Par dÃ©faut, PostgreSQL rassemble les statistiques sur une base rÃ©guliÃšre. NÃ©anmoins, si vous changez dramatiquement le contenu de vos tables dans une pÃ©riode courte, les statistiques ne seront alors plus Ã  jour.
+In order to figure out what situation it is dealing with (reading a small part of the table versus reading a large portion of the table), PostgreSQL keeps statistics about the distribution of data in each indexed table column.  By default, PostgreSQL gathers statistics on a regular basis. However, if you dramatically change the make-up of your table within a short period of time, the statistics will not be up-to-date.
 
-Pour vous assurez que les statistiques correspondent bien au contenu de la table actuelle, il est courant d'utiliser la commande ``ANALYZE`` aprÃšs un grand nombre de modifications ou de suppression de vos donnÃ©es. Cela force le systÃšme de gestion des statistiques Ã  rÃ©cupÃ©rer l'ensemble des donnÃ©es des colonnes indexÃ©es.
+To ensure your statistics match your table contents, it is wise the to run the ``ANALYZE`` command after bulk data loads and deletes in your tables. This force the statistics system to gather data for all your indexed columns.
 
-La commande ``ANALYZE`` demande Ã  PostgreSQL de parcourir la table et de mettre Ã  jour les statistiques utilisÃ©es par le planificateur de requÃªtes (la planification des requÃªtes sera traitÃ© ultÃ©rieurement).
+The ``ANALYZE`` command asks PostgreSQL to traverse the table and update its internal statistics used for query plan estimation (query plan analysis will be discussed later). 
 
 .. code-block:: sql
 
    ANALYZE nyc_census_blocks;
-
-NÃ©ttoyage
+   
+Vacuuming
 ---------
 
-Il est souvent stressant de constater que la simple crÃ©ation d'un index n'est pas suffisant pour que PostgreSQL l'utilise efficacement. Le nettoyage doit Ãªtre rÃ©alisÃ© aprÃšs qu'un index soit crÃ©Ã© ou aprÃšs un grand nombre de requÃªtes UDATE, INSERT ou DELETE ait Ã©tÃ© rÃ©alisÃ© sur une table. La commande ``VACUUM`` demande Ã  PostgreSQL de rÃ©cupÃ©rer chaque espace non utilisÃ© dans les pages de la table qui sont laissÃ©es en l'Ã©tat lors des requÃªtes UPDATE ou DELETE Ã  cause du modÃšle d'estampillage multi-versions.
+It's worth stressing that just creating an index is not enough to allow PostgreSQL to use it effectively.  VACUUMing must be performed whenever a new index is created or after a large number of UPDATEs, INSERTs or DELETEs are issued against a table.  The ``VACUUM`` command asks PostgreSQL to reclaim any unused space in the table pages left by updates or deletes to records. 
 
-Le nettoyage des donnÃ©es est tellement important pour une utilisation efficace du serveur de base de donnÃ©es PostgreSQL qu'il existe maintenant une option "autovacuum".
+Vacuuming is so critical for the efficient running of the database that PostgreSQL provides an "autovacuum" option.
 
-ActivÃ©e par dÃ©faut, le processus autovacuum nettoie (rÃ©cupÃšre l'espace libre) et analyse (met Ã  jour les statistiques) vos tables suivant un intervalle donnÃ© dÃ©terminÃ© par l'activitÃ© des bases de donnÃ©es. Bien que cela fonctionne avec les bases de donnÃ©es hautement transactionnelles, il n'est pas supportable de devoir attendre que le processus autovacuum se lance lors de la mise Ã  jour ou la suppression massive de donnÃ©es. Dans ce cas, il faut lancer la commande ``VACUUM`` manuellement.
+Enabled by default, autovacuum both vacuums (recovers space) and analyzes (updates statistics) on your tables at sensible intervals determined by the level of activity.  While this is essential for highly transactional databases, it is not advisable to wait for an autovacuum run after adding indices or bulk-loading data.  If a large batch update is performed, you should manually run ``VACUUM``.
 
-Le nettoyage et l'analyse de la base de donnÃ©es peuvent Ãªtre rÃ©alisÃ©s sÃ©parÃ©ment si nÃ©cessaire. Utiliser la commande ``VACUUM`` ne mettra pas Ã  jour les statistiques alors que lancer la commande ``ANALYZE`` ne rÃ©cupÃšrera pas l'espace libre des lignes d'une table. Chacune de ces commandes peut Ãªtre lancÃ©e sur l'intÃ©gralitÃ© de la base de donnÃ©es, sur une table ou sur une seule colonne.
+Vacuuming and analyzing the database can be performed separately as needed.  Issuing ``VACUUM`` command will not update the database statistics; likewise issuing an ``ANALYZE`` command will not recover unused table rows.  Both commands can be run against the entire database, a single table, or a single column.
 
 .. code-block:: sql
@@ -134,14 +134,14 @@
    VACUUM ANALYZE nyc_census_blocks;
 
-Liste des fonctions
--------------------
+Function List
+-------------
 
-`geometry_a && geometry_b <http://postgis.org/docs/ST_Geometry_Overlap.html>`_: retourne TRUE si l'Ã©tendue de A chevauche celle de B.
+`geometry_a && geometry_b <http://postgis.org/docs/ST_Geometry_Overlap.html>`_: Returns TRUE if A's bounding box overlaps B's.
 
-`geometry_a = geometry_b <http://postgis.org/docs/ST_Geometry_EQ.html>`_: retourne TRUE si l'Ã©tendue de A est la mÃªme que celle de B.
+`geometry_a = geometry_b <http://postgis.org/docs/ST_Geometry_EQ.html>`_: Returns TRUE if A's bounding box is the same as B's.
 
-`ST_Intersects(geometry_a, geometry_b) <http://postgis.org/docs/ST_Intersects.html>`_: retourne TRUE si la gÃ©omÃ©trie *a* "intersecte spatialement" la gÃ©omÃ©trie '*b*- (si elles ont une partie en commun) et FALSE sinon (elles sont disjointes).
+`ST_Intersects(geometry_a, geometry_b) <http://postgis.org/docs/ST_Intersects.html>`_: Returns TRUE if the Geometries/Geography "spatially intersect" - (share any portion of space) and FALSE if they don't (they are Disjoint). 
 
-.. rubric:: Notes de bas de page
+.. rubric:: Footnotes
 
 .. [#RTree] http://postgis.org/support/rtree.pdf
