Mise en place de la base PostreSQL

Avant toute chose il est nécessaire d'avoir en place un serveur PostgreSQL et de connaître l'utilisation rudimentaire du client psql. Pour accueillir la copie de Wikipédia, il est nécessaire de créer une base de données, la configurer et créer la structure des tables nécessaires. Toute cette partie se réalise en tant qu'utilisateur postgres (le super-utilisateur de PostgreSQL) avec le client psql :

shell$ sudo -u postgres psql
Bienvenue dans psql 8.3.7, l'interface interactive de PostgreSQL.

Saisissez:
    \copyright pour les termes de distribution
    \h pour l'aide-mémoire des commandes SQL
    \? pour l'aide-mémoire des commandes psql
    \g ou point-virgule en fin d'instruction pour exécuter la requête
    \q pour quitter

postgres=#

Il faut d'abord créer une base de données encodé en utf-8. Pour des raisons de sécurité, il vaut mieux que la base soit affectée à un utilisateur ayant moins de privilèges que le super-utilisateur. Une fois créée il faut se connecter à cette dernière base pour la configurer :

postgres=# CREATE DATABASE wikinews ENCODING 'utf-8' OWNER <username>;
CREATE DATABASE
postgres=# \c wikinews
Vous êtes maintenant connecté à la base de données « wikinews ».

Il est ensuite nécessaire d'activer le langage PL/SQL pour les triggers du schéma de données :

postgres=# CREATE FUNCTION plpgsql_call_handler ()
wikinews-#  RETURNS LANGUAGE_HANDLER AS 'plpgsql' LANGUAGE C;
CREATE FUNCTION
postgres=# CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql HANDLER plpgsql_call_handler;
INFO:  utilisation des informations de pg_pltemplate au lieu des paramètres de
CREATE LANGUAGE
CREATE LANGUAGE

Le schéma de données de MediaWiki fait appel aux capacités de recherche en texte plein de PostgreSQL. Il est nécessaire de créer la configuration default utilisée dans le schéma de données. Plusieurs configurations sont disponibles par défaut, pour obtenir une liste il suffit d'utiliser la commande \dF.

Nous allons utiliser dans le cas présent la configuration fournie pour le traitement des textes en français :

postgres=# CREATE TEXT SEARCH CONFIGURATION public.default ( COPY = pg_catalog.french );

Mise en place du schéma de la base

L'importation du schéma de la base va se faire en tant qu'utilisateur classique, il faut donc d'abord s'assurer qu'il est possible de se connecter avec ledit utilisateur. Quittez la connexion super-utilisateur par la commande \q, puis connectez-vous :

shell$ psql -U<username> wikinews
Bienvenue dans psql 8.3.7, l'interface interactive de PostgreSQL.

Saisissez:
    \copyright pour les termes de distribution
    \h pour l'aide-mémoire des commandes SQL
    \? pour l'aide-mémoire des commandes psql
    \g ou point-virgule en fin d'instruction pour exécuter la requête
    \q pour quitter

wikinews=>

Les schémas de MédiaWiki sont disponibles en ligne, il faut bien sûr faire attention à récupérer la version pour PostgreSQL. Récupérez le fichier tables.sql, puis chargez-le dans psql :

wikinews=> \i tables.sql
...
wikinews=> commit;
COMMIT

Si jamais l'authentification en tant qu'utilisateur classique ne fonctionne pas, il est possible de changer le mot de passe en tant que super-utilisateur à l'aide de la requête : ALTER USER <username> PASSWORD '<password>';

Importation des données

Le site download.wikipedia.org fourni toutes les exportations possibles du projet Wikipédia et de ses dérivés. Nous sommes plus particulièrement intéressés par la section Database backup dumps. Pour l'exemple nous allons utiliser l'export complet, révisions comprises, de Wikinews en français : export du 13 Juillet 2009.

Pour l'import en base nous allons utiliser l'outil mwdumper développé dans le cadre du projet Wikipédia. Au moment où ce billet est rédigé il y a quelques bugs qui empêchent l'import dans PostgreSQL à cause d'un mauvais échappement des chaînes de caractères. J'ai modifié le programme pour résoudre ces problèmes, je vous conseille donc d'utiliser la version corrigée de mwdumper en attendant que mes patchs soient intégrés (entrée bugzilla).

De plus l'opération d'import doit être réalisée en tant que super-utilisateur afin de pouvoir désactiver les triggers liées aux contraintes de clefs étrangère. Il faut alors ouvrir un shell en utilisateur postgres puis lancer l'import :

shell$ sudo -u postgres -s
postgres@shell$ java -jar my-mwdumper.jar --format=pgsql:1.5 frwikinews-20090713-pages-meta-history.xml.bz2|psql wikinews

L'importation est très longue : pour la centaine de milliers d'entrées de wikinews, ça a pris presque trois heures sur ma machine. Mais une fois que tout est importé, il est possible d'accéder à tout le contenu en quelques requêtes. Par exemple, le nombre de révisions par page :

  1. SELECT rev_page,count(rev_id) AS nbrev FROM revision GROUP BY rev_page ORDER BY nbrev DESC;

Enjoy...

UPDATE : Importation sans être super-utilisateur

Comme l'explique ce billet, il est possible de retarder la vérification des contraintes d'intégrité, ce qui ne nécessite pas d'être super-utilisateur (nouveau bug remonté). Toutefois, pour ce faire, il est nécessaire de rendre les contraintes DEFERRABLE, en d'autres termes que celles-ci puissent être mises en application à la fin de la transaction plutôt qu'au fur et à mesure des insertions. De plus il faut supprimer la contrainte de la table revision qui fait référence aux utilisateurs car ces derniers ne sont pas exportés dans les dumps.

En attendant la mise en application de mon patch, utilisez la version patchée du schéma SQL disponible ici. Il vous faudra supprimer le schéma existant, je n'ai pas réussi à rendre les contraintes DEFERRABLE sans recréer les tables.

Le reste de la procédure est similaire, excepté qu'il faille intercepter la désactivation des triggers et je n'ai pas trop le courage de faire un nouveau patch pour mwdumper pour le moment, petite bidouille donc :

monuser$ java -jar my-mwdumper.jar --format=pgsql:1.5 frwikinews-20090713-pages-meta-history.xml.bz2|sed s'/.*\(DISABLE\|ENABLE\) TRIGGER.*//'|sed 's/BEGIN;/BEGIN;SETCONSTRAINTS ALL DEFERRED;/'|psql wikinews

Un billet plus complet détaille la nouvelle procédure : Insérer plusieurs copies locales de Wikipedia dans une base PostgreSQL