[mySQL] Découper une table et gagner en performance ?

WRInaute discret
Bonjour,

J'ai besoin d'un conseil concernant la découpe d'une table. (en vue de la rendre moins lourde et de l'accélérer)

Ma table est assez lourde et certains champs ne sont pas utilisés par tous les enregistrements.

Exemple: Chaque enregistrement possède un champs description (type TEXT) mais ce champs est facultatif donc pour la moitié des enregistrements ce champs est vide.

Est-ce que je gagnerai beaucoup en performance si j'enleve le champs description de la table pour la mettre dans une autre table.

Cette technique diminuerai surement la taille de la table mais cela ajouterai une jointure en plus lorsque je ferai un select.

Qu'en pensez-vous?

Merci

A bientôt.
 
WRInaute impliqué
elle est lourde comment ? Car si c'est pour diviser 1000 enregistrements en 2x 500 moi je dis non.
En fait je suis pas sûr dans tous les cas qu'il y ait une bonne raison.

Jacques, si tu passes par là, on a besoin de tes compétences !
 
WRInaute passionné
dans le cas de plusieurs centaines de milliers d'enregistrements (plusieurs millions même) la séparation de données texte et numériques est une très bonne chose. L'ajout d'un ID (INT) dans la première table ramenant sur les données TXT de la 2eme est la solution la plus simple a mettre en place... un bon INDEX sur la 2eme et le tour est joué, les gains de performance (surtout s'il y a de nombreux SELECT n'est carrement pas négligeable . Dans le cas d'une table avec très peu d'enregistrement je ne suis cependant pas sur qu'en terme de vitesse tu ne perdrais pas quelques ms...
 
WRInaute accro
Pas un grand spécialiste de la façon dont mySQL fait ça (moi je suis plutôt Postgresql), et ça doit en plus varier suivant que tu utilises du myIsam ou du InnoDB, mais quelques pistes:
- si toute ta base tient en RAM en permanence et que tu fais surtout des lectures et éventuellement des ajouts (mais pas de modifs), ça ne devrait rien changer
- si tu as beaucoup de modifs (sur les champs autre que le "gros" champ texte), il peut en effet être utile de séparer les deux (dans un environnement ACID il est nécessaire de faire des copies de la ligne complète à chaque modif, ce qui veut dire qu'il y aura beaucoup d'accès disque)
- ça dépend probablement pas mal de la taille de tes champs texte
- ça dépend aussi des accès que tu fais. Si tu as les bons index et que toutes les requêtes les utilisent, ça ne devrait pas changer grand chose. Si par contre les requêtes que tu effectues n'utilisent pas d'index, ça peut faire une différence non négligeable (vu qu'il faut qu'il lise toute la table pour trouver les bons enregistrements, plus la table à lire est petite, mieux c'est). Evidemment si c'est une recherche genre LIKE '%toto%' sur le champ texte, ça ne va rien changer.
- ça dépend aussi du fait que tu aies besoin du champ en question à chaque requête ou pas, et dans le deuxième cas, de la proportion des requêtes qui en ont besoin ou pas...

Bref, réponse de normand, ptet ben qu'oui, ptet ben qu'non, ça dépend. En ce qui me concerne, pour une table de cette taille, si tu n'as pas un serveur sérieusement sous-dimensionné, je ne m'embêterais pas trop, mais je m'assurerais quand même qu'il y a les bons index et qu'ils sont utilisés.

Jacques.
 
WRInaute passionné
As-tu testé d'autres moteurs de stockage ?
innoDB, voir memory (attention, si t'as un crash tu perds tout donc backup fréquent).

En innoDB, tu ne pourras pas faire d'INDEX de type FULLTEXT, la technique est donc de balancer ces fulltext dans une autre table qui n'est "tappé" que quand c'est vraiment nécessaire.

Si ta table (par exemple "user") prends aussi en compte, en bas de chaque page un champ "last visit" tu peux "cacher" cette valeur :
Code:
if (!$memcache->get('lastvisit' . $userid)) {
$sql = 'update user set lastvisit = NOW() WHERE id = \'' . $userid . '\';';
$DB->query($sql);
$memcache->set('lastvisit' . $userid, 1, 0, 360);
}
Code à vérifier mais voilà ce que j'utilisais pour mettre à jour leurs ip/lastvisit etc ;)
Ca permet d'effectuer cette requête uniquement toute les 360 secondes.

Pour les visites d'un forum par exemple, tu peux utiliser la même technique avec $memcache->increment. Si ça arrive au dessus de 10, tu rajoutes + 10 au post du forum et donc tu fais 10 fois moins de mises à jour de tables.
 
WRInaute passionné
Dans le cas du post, (80K enregistrements) je penche ++ pour la separation car :
-> cela ne prends pas énormément de temps a modifier (dans le cas d'un dev propre)
-> même si les perfs ne sont pas de suite au rendez-vous --> cela sera un bon saut pour la suite ...

Manque peut être quelques infos concernant en effet le serveur (dixit jcaron)
 
WRInaute passionné
seebz a dit:
Si tu es en MySQL 5.1, il y aussi le partitionnement de table.
Je n'ai pas encore eu l'occasion d'essayer mais il semblerait que ce soit prévu pour ce genre de cas.

https://www.google.fr/search?q=partitionnement+mysql+5.1
Si tu es en innoDB, tu peux aussi prendre 10 Disques dur sur ta machine et séparer les IBData en autant de partition que de disques. Là les stats seront au rendez-vous, mais bon, rien ne vaut de l'optimisation au niveau de PHP aussi ;)
 
Discussions similaires
Haut