acceleration d'une requete select en mysql

acceleration d'une requete select en mysql - SQL/NoSQL - Programmation

Marsh Posté le 22-04-2003 à 10:18:48    

Bonjour a tous
J'ai une petite question a vous poser,  
Comment faire pour accelerer une recherche dans une table, tel que "select id_skieur where specialité = "descente" ".  
Merci

Reply

Marsh Posté le 22-04-2003 à 10:18:48   

Reply

Marsh Posté le 22-04-2003 à 10:34:13    

plutôt que d'utiliser une chaine dans ton champ, prends un entier qui correspondra à chaque spécialité
 
par exemple un chti tableau php
 
$Specialite = array (0 => 'descente',1 => 'slalom';);
 
si dans ton champ tu as 1, tu fais la correspondance avec ton tableau, ce qui donne 'slalom'
 
comme les SGBD sont bien plus rapides avec des chiffres que des chaines, t'as optimisé ta base  ;)
 
PS : tu peux aussi ajouter un index sur ce champ


Message édité par Sh@rdar le 22-04-2003 à 10:34:55
Reply

Marsh Posté le 22-04-2003 à 10:46:59    

@Sh@rdar
 
Comment faire pour faire un index sur ce champs. Je debute, donc je ne sais pas trés bien a quoi correspond un index, et comment les realiser. :??:

Reply

Marsh Posté le 22-04-2003 à 10:58:40    

tu utilise quoi pour attaquer ta base ?
 
dans phpmyadmin, sur la page de propriétés de la table, tu cliques sur 'index' en face du champ concerné

Reply

Marsh Posté le 22-04-2003 à 11:13:44    

@Sh@rdar  
 
Tu entend quoi par "attaquer"?
 
j'utilise pas phpmyadmin, j'utilise WinMySQLAdmin. Et c'est uniquement du code que je tape, tu sais pas ce que je dois taper pour indexer un champs?
 

Reply

Marsh Posté le 22-04-2003 à 11:15:55    

toutoun88 a écrit :

@Sh@rdar  
 
Tu entend quoi par "attaquer" :gun: ?
 
j'utilise pas phpmyadmin, j'utilise WinMySQLAdmin. Et c'est uniquement du code que je tape, tu sais pas ce que je dois taper pour indexer un champs?
 


 
:gun: :gun: :gun:
 
Tu utilises quoi pour y avoir acces ? Pour consulter, modifier...


Message édité par pyrojb le 22-04-2003 à 11:16:51
Reply

Marsh Posté le 22-04-2003 à 11:22:43    

c'est WinMySQLAdmin, ensuite, c'est tout sous dos.

Reply

Marsh Posté le 22-04-2003 à 11:32:44    

tu peux pas le faire avec cet outil là
 
faut se palucher la requête SQL
 
 
 

Citation :


 
7.26 CREATE INDEX
CREATE [UNIQUE] INDEX Nom_indexON Nom_table (Nom_col[(longueur]),... )
 
The CREATE INDEX n'est disponible qu'à partir de la version 3.22. CREATE INDEX est un raccourci de ALTER TABLE qui crée des index. ALTER TABLE  
 
Généralement, il est possible de créer des tous les index d'une table au moment de la création de la table, avec CREATE TABLE. CREATE TABLECREATE INDEX permettra alors d'ajouter de nouveaux index.  
 
Une liste de nom de colonne de format (col1,col2,...) créer un index de multiples colonnes. Les index sont formés en concaténant les différentes valeurs en une ligne.  
 
Pour les valeurs de type CHAR et VARCHAR , les index peuvent ne prendre en compte qu'une partie de la colonne, en précisant Nom_col(longueur) . (Avec les types BLOB et TEXT, cette longueur est obligatoire. ). La commande suivante montre comment créer un index sur les 10 premiers caractères d'une colonne :  
 
mysql> CREATE INDEX part_of_name ON customer (name(10));
 
Etant donné que la plus part des mots diffèrent les uns des autres dans les 10 premières lettres, l'index crée ne devrait pas être moins efficace que la colonne, tout en étant nettement plus rapide. Faire des index à valeur partiel permet de réduire la taille des index, et d'accélérer les opération de tris et d'insertion.  
 
Il faut noter que l'on peut ajouter à un index une colonne qui accepte les types NULL, que depuis la version 3.23.2 de MySQL. De même pour les colonnes de type BLOB/TEXT. Cela impose l'utilisation du format de table MyISAM.  
 


Message édité par Sh@rdar le 22-04-2003 à 11:33:05
Reply

Marsh Posté le 22-04-2003 à 11:45:24    

donc si j'ai bien compris ton truc, il faudrait faire  
CREATE INDEX spec ON skieur (specialité (varchar(20));
 
Mais je ne comprend pas du tout pourquoi il faut lui mettre un nom (nom_index), apres, si je fais un select avec un where contenant specialité, il va automatiquement utiliser l'index, ou faut lui preciser?  
 

Reply

Marsh Posté le 22-04-2003 à 11:56:04    

relis bien, tu ne dois spécifier la longueur que pour créer un index sur un champ de type CHAR / VARCHAR
 
en utilisant un entier, tu fais juste CREATE INDEX(`monchamp`) ON `matable`
ou ALTER TABLE `matable` ADD INDEX(`monchamp`)


Message édité par Sh@rdar le 22-04-2003 à 11:56:49
Reply

Marsh Posté le 22-04-2003 à 11:56:04   

Reply

Marsh Posté le 22-04-2003 à 12:21:56    

Juste un truc : à partir du moment où le champ est indexé, il n'y a aucune différence de performance entre un champ numérique ou un champ alphanumérique.

Reply

Marsh Posté le 22-04-2003 à 12:44:12    

toutoun88 a écrit :


Mais je ne comprend pas du tout pourquoi il faut lui mettre un nom (nom_index), apres, si je fais un select avec un where contenant specialité, il va automatiquement utiliser l'index, ou faut lui preciser?  


Oui, l'optimiseur de requête va choisir l'index qui correspond le mieu à ta requête, c'est à dire l'index qui contient le plus de champs utilisés parmis les champs utilisés dans tes critères.
 
Pour le nom, il sert simplement à retrouver ton index quand tu en a besoin :
-> Vu qu'on peut créer plusieurs indexes sur une même table, lorsque tu veux en modifier un/supprimer un, il faut pouvoir le reconnaître.

Reply

Marsh Posté le 22-04-2003 à 13:50:57    

@MagicBuzz, Sh@rdar
 
Merci, grace a vous j'ai compris. En fait je ne savais pas pourquoi il fallait lui donner un nom.
A +

Reply

Marsh Posté le 22-04-2003 à 13:55:24    

Encore une petite question, si je comprend bien la syntaxe, on peux mettre plusieurs champs pour le même index. A quoi sa sert, et comment ça marche?

Reply

Marsh Posté le 22-04-2003 à 13:59:23    

Encore une petite en fait:
Est-ce que ça sert a quelque chose d'indexer les clé primaire?
A quoi servent les "foreign key" et les "key" simple?

Reply

Marsh Posté le 22-04-2003 à 14:54:41    

Les clés primaires sont automatiquement indexée (sauf sur les vieux SGBD).
 
Il est très intéressant de faire des indexes portant sur plusieurs colonnes, car pour une requête donnée, un seul index pourra être utilisé par table.
 
Donc si une requête possède deux filtres, par exemple :
 
couleur = 'Rouge' et poids > 2
 
A ce moment, il faudra un index sur les deux champs à la fois pour profiter pleinement de l'index.
 
Sinon, pour ce qui est des primary key, ce sont les clés.
Elles peuvent porter sur un unique champ (unique id) ou un sur plusieurs champs (doublets, triplets, etc.)
 
Par exemple, pour un utilisateur, on aura une clé primaire "user_id" ou "login", selon le choix, qui est unique et forcément remplis pour chaque utilisateurs.
 
Il y aura aussi une clé alternative, qui portera sur le couplet "login/password", afin d'interdire que deux utilisateurs aient les mêmes login/pass. Une dernière clé alternative pourra porter sur l'email, afin d'éviter que deux utilisateurs utilisent la même email.
 
Les clés en tant que telles sont de moins en moins utilisées. On utilise généralement des index uniques, qui permettent de faire les mêmes chose, mais avec un certain nombre de vérifications en moins, ce qui accélère la base. Il est cependant recommendé de toujours définir au moins une clé primaire par table (les index uniques ne seront utilisés que pour les clés alternatives).
 
 
Pour ce qui est des "foreign key", elles servent à indiquer que les valeurs d'un champ proviennent d'une autre table. Cela correcpond à un lien 1,n ou 0,n en MERISE.
 
Cela permettra notamment d'interdire de créer un produit avec comme code famille "PAPER" si aucune famille de cet id n'est déclarée, ou aussi, ça interdira de supprimer une famille tant qu'elle contiendra des membres.
Les clés étrangères créent aussi des indexes, qui permettent d'optimiser considérablement les jointures. Avec une clé primaire correctement créé, on peut même se passer de rappeler le champ de jointure dans la requête, même si c'est absoluement déconseillé.
Par exemple :
 
si la table "produit" à comme clé étrangère "fam_id" qui pointe sur l'"id" de la table "famille", alors les deux requêtes soivantes reviennent au même :
 
select famille.fam_nom from famille, produit where produit.poids > 2
 
select famille.fam_nom from famille, produit where famille.id = produit.fam_id and produit.poids > 2
 
Par contre ! Si la clé étrangère n'est pas créé, la première requête retournera une ligne de famille par ligne de produit valide, car le SGBD sera incapable de retrouver le lien entre les deux tables. Il est donc très fortement déconseillé d'omettre les champs de jointure, même s'ils ne sont pas indispensables dans le cas d'un table correcte.
 
Pour terminer, une dernière petite subtilité :
 
soit une table "utilisateur", une table "article", et une table "vote".
 
La table utilisateur a pour clé primaire "user_id".
 
Article et Vote ont comme clé étrangère "user_id", qui pointe sur "user_id" de "utilisateur".
 
Un article est écrit par un utilisateur.
Un vote est effectué par des utlisateurs à propos d'un article.
 
Mettons que tu veux retrouver le moyenne des votes pour l'article "1", sans prendre en compte le vote de l'auteur de l'article.
 
Tu vas écrire :
 
select avg(vote.note)
from vote, article
where article.id = 1
and vote.user_id <> article.user_id
 
Si "user_id" des deux tables n'est pas déclaré en tant que clé étrangère, mais juste indexé, alors pour "article", l'optimiseur ne saura s'il doit prendre l'index qui pointe sur "id" ou "user_id" dans la table article. Les perfs seront donc moyennes.
 
Si ces deux champs sont convenablement déclarés comme clé étrangères, alors l'optimiseur va intégré lui-même la table "utilisateur" à le requête, et utiliser automatiquement les indexs correspondant aux clés étrangères. Il pourra dont en plus utilise l'index pointant sur "article.id". Les performances seront donc très largement suppérieures.

Reply

Marsh Posté le 22-04-2003 à 15:19:11    

Ok, ça m'a bien été utile ton discours!
 
J'ai une petite base a montrer, mais que je n'ai pas encore créé. Je voudrais qu'on me dise ce qui ne va pas (car je sais que ça ne va pas.
 
CREATE TABLE produit (  
 
CAS_number VARCHAR(20) NOT NULL,        
quality VARCHAR(20) NOT NULL,
 
name VARCHAR(50) NOT NULL,
synonym VARCHAR(255),
Formula VARCHAR(30) NOT NULL,
 
PRIMARY KEY (CAS_number, quality),
INDEX name_index (name),
INDEX formula_index (formula)  
 
)
 
 
CREATE TABLE precision_produit (
 
CAS_number VARCHAR(20) NOT NULL,  
quality VARCHAR(20) NOT NULL,
 
transmission_UV VARCHAR(100),
eau VARCHAR(100),
residus_non_volatiles VARCHAR(100),
 
PRIMARY KEY (CAS_number, quality),
FOREIGN KEY (CAS_number) REFERENCES produit (CAS_number)
FOREIGN KEY (quality) REFERENCES produit (quality)
 
)
 
 
CREATE TABLE conditionnement (
 
CAS_number VARCHAR(20) NOT NULL,
quality VARCHAR(20), NOT NULL
 
fournisseur VARCHAR(20) NOT NULL,  
product_code VARCHAR(20) NOT NULL,  
box_quantity_1 INTEGER(3) NOT NULL,
box_quantity_2 INTEGER(3),
box_quantity_3 INTEGER(3),
packaging_quantity_1 DOUBLE(6,3) NOT NULL,  
packaging_quantity_2 DOUBLE(6,3),
packaging_quantity_3 DOUBLE(6,3),
packaging_unit VARCHAR(10) NOT NULL,
price_1 DOUBLE(6,3) NOT NULL,  
price_2 DOUBLE(6,3),
price_3 DOUBLE(6,3),
 
PRIMARY KEY (CAS_number, quality),
FOREIGN KEY (CAS_number) REFERENCES produit (CAS_number)
FOREIGN KEY (quality) REFERENCES produit (quality)
 
)
 
 
J'ai compris qu'il ne voulait pas que la même clé primaire existe dans deux tables differentes. Dois-je mettre un id a chaque table?
Peut on me dire comment l'optimiser.
 
PS: la decoupe des table peut paraitre illogique, mais il faut savoir qu'un produit sur 10 possede des precisions_produits et on m'a dit qu'il vallait mieux eviter les "blancs" dans les tables.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed