un passage quasi-obligatoire pour faire des sites web dynamiques

22.Temps d'execution

22.1.Introduction:

L'objectif de ce chapitre est de prendre conscience des temps d'execution induits par le choix de tel ou tel attribut dans une base de données. Pour cela, des mesures ont été réalisées sur une base de données MySQL, via des scripts PHP, sous le système d'exploitation Linux, sur une machine de performance modeste (PC AMD 350MHz, 192Mo de mémoire, DD IBM-DLTA 30Go sur UDMA33).
Les temps d'execution n'ont pas de signification en soit (car ils dépendent beaucoup du système) par contre les temps relatifs permettent de tirer des enseignements.
Les résultats complets sont disponibles à la fin de ce chapitre.

22.2.Dimensionnement:

Pour commencer, nous avons simplement inseré 200 enregistrements dans une table ne contenant qu'un simple champs de type entier. Puis nous avons lu (requête SELECT) 20 de ces enregistrements et effectué 2 opérations (SUM et COUNT).
L'insertion a demandé un dixième de seconde. La lecture a demandé 2 centièmes de seconde (soit à peu près un millième de seconde par enregistrement lu). Quant aux 2 opérations, elles ont chacune demandé moins d'un centième de seconde.
Conclusion: Une base de données est conçue pour traiter un très grand nombre d'enregistrements. Dans ce contexte, une table de 200 enregistrements peut être considérée comme de taille négligeable.

22.3.Avec ou Sans index:

Ensuite, nous avons voulu démontrer l'utilité (ainsi que la contre-partie) d'indexer les champs sur lequels portent les requêtes.
Pour cela, nous avons inséré dans différentes tables (indexées ou non), un nombre croissant d'enregistrements. Enregistrements que nous avons par la suite lu par 20 requêtes SELECT portant chacune sur un enregistrement différent (tiré au hasard).
Nb d'enregistrementsINSERTSELECTSUM
SANS INDEXAVEC INDEXSANS INDEXAVEC INDEXSANS INDEXAVEC INDEX
2000.100.110.020.0200
1000055.90.290.020.020.04
10000049.761.62.70.020.150.38
1000000493632270.021.54.1
Les temps sont exprimés en secondes.
Conclusion: L'utilisation d'un index sur un champ augmente la durée de l'insertion d'un nouveau champ (temps de mise à jour de l'index) de l'ordre de 30% dans notre cas. Par contre, le temps de recherche s'en trouve considérablement réduit. Dans notre cas, il devient indépendant de la taille de la table ce qui nous donne un gain de 99.92% sur la table de 100000 enregistrements.
Plus curieusement, l'utilisation affecte également l'opération SUM dont le temps d'execution se trouve ici augmenté de 173%. L'opération COUNT, elle, ne nécessitant pas d'accès au contenu de la table se fait toujours en un temps négligeable.

22.4.Bench MySQL

Serveur : Apache/1.3.20 (Unix) PHP/4.0.6
Machine : i386-redhat-linux-gnu
OS : linux-gnu
CPU (famille) : i386
RequêteFonctionTypeNb d'enreg.Avec/Sans IndexRésultatTemps d'execution en s
Avec 200 enregistrements de type ENTIER
INSERTRANDINTEGERSANS INDEX2000.11
SELECTCOUNTINTEGERSANS INDEX2002000
SELECTSUMINTEGERSANS INDEX2002208193922950
SELECTRAND (x20)INTEGERSANS INDEX2000.02
INSERTRANDINTEGERAVEC INDEX2000.12
SELECTCOUNTINTEGERAVEC INDEX2002000
SELECTSUMINTEGERAVEC INDEX2001953277114090
SELECTRAND (x20)INTEGERAVEC INDEX2000.02
Avec 200 enregistrements de type VARCHAR(32)
INSERTRANDVARCHAR(32)SANS INDEX2000.11
SELECTCOUNTVARCHAR(32)SANS INDEX2002000
SELECTRAND (x20)VARCHAR(32)SANS INDEX2000.03
SELECTLIKE %RAND% (x20)VARCHAR(32)SANS INDEX2000.04
INSERTRANDVARCHAR(32)AVEC INDEX2000.13
SELECTCOUNTVARCHAR(32)AVEC INDEX2002000
SELECTRAND (x20)VARCHAR(32)AVEC INDEX2000.03
SELECTLIKE %RAND% (x20)VARCHAR(32)AVEC INDEX2000.03
Avec 10000 enregistrements de type ENTIER
INSERTRANDINTEGERSANS INDEX100005.4
SELECTCOUNTINTEGERSANS INDEX10000100000
SELECTSUMINTEGERSANS INDEX10000107534761978550.02
SELECTRAND (x20)INTEGERSANS INDEX100000.33
INSERTRANDINTEGERAVEC INDEX100006.4
SELECTCOUNTINTEGERAVEC INDEX10000100000
SELECTSUMINTEGERAVEC INDEX10000107854392440200.04
SELECTRAND (x20)INTEGERAVEC INDEX100000.02
Avec 10000 enregistrements de type VARCHAR(32)
INSERTRANDVARCHAR(32)SANS INDEX100005.5
SELECTCOUNTVARCHAR(32)SANS INDEX10000100000
SELECTRAND (x20)VARCHAR(32)SANS INDEX100000.75
SELECTLIKE %RAND% (x20)VARCHAR(32)SANS INDEX100000.99
INSERTRANDVARCHAR(32)AVEC INDEX100007.2
SELECTCOUNTVARCHAR(32)AVEC INDEX10000100000
SELECTRAND (x20)VARCHAR(32)AVEC INDEX100000.03
SELECTLIKE %RAND% (x20)VARCHAR(32)AVEC INDEX100000.88
Avec 100000 enregistrements de type ENTIER
INSERTRANDINTEGERSANS INDEX10000054.9
SELECTCOUNTINTEGERSANS INDEX1000001000000
SELECTSUMINTEGERSANS INDEX1000001073513185651640.14
SELECTRAND (x20)INTEGERSANS INDEX1000003.1
INSERTRANDINTEGERAVEC INDEX10000066.7
SELECTCOUNTINTEGERAVEC INDEX1000001000000
SELECTSUMINTEGERAVEC INDEX1000001073643789706300.39
SELECTRAND (x20)INTEGERAVEC INDEX1000000.02
Avec 100000 enregistrements de type VARCHAR(32)
INSERTRANDVARCHAR(32)SANS INDEX10000054.8
SELECTCOUNTVARCHAR(32)SANS INDEX1000001000000
SELECTRAND (x20)VARCHAR(32)SANS INDEX1000006.9
SELECTLIKE %RAND% (x20)VARCHAR(32)SANS INDEX1000008.8
INSERTRANDVARCHAR(32)AVEC INDEX10000074.4
SELECTCOUNTVARCHAR(32)AVEC INDEX1000001000000
SELECTRAND (x20)VARCHAR(32)AVEC INDEX1000000.03
SELECTLIKE %RAND% (x20)VARCHAR(32)AVEC INDEX1000008.5
Avec 1000000 enregistrements de type ENTIER
INSERTRANDINTEGERSANS INDEX1000000550
SELECTCOUNTINTEGERSANS INDEX100000010000000
SELECTSUMINTEGERSANS INDEX100000010742797917844961.5
SELECTRAND (x20)INTEGERSANS INDEX100000030.7
INSERTRANDINTEGERAVEC INDEX1000000689
SELECTCOUNTINTEGERAVEC INDEX100000010000000
SELECTSUMINTEGERAVEC INDEX100000010732756637645864.7
SELECTRAND (x20)INTEGERAVEC INDEX10000000.02
Avec 1000000 enregistrements de type VARCHAR(32)
INSERTRANDVARCHAR(32)SANS INDEX1000000566
SELECTCOUNTVARCHAR(32)SANS INDEX100000010000000
SELECTRAND (x20)VARCHAR(32)SANS INDEX100000070.4
SELECTLIKE %RAND% (x20)VARCHAR(32)SANS INDEX100000089.9
INSERTRANDVARCHAR(32)AVEC INDEX1000000827
SELECTCOUNTVARCHAR(32)AVEC INDEX100000010000000
SELECTRAND (x20)VARCHAR(32)AVEC INDEX10000000.03
SELECTLIKE %RAND% (x20)VARCHAR(32)AVEC INDEX100000088.6