acceleration d'une requete select en mysql - SQL/NoSQL - Programmation
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
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.
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é
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?
Marsh Posté le 22-04-2003 à 11:15:55
toutoun88 a écrit : @Sh@rdar |
Tu utilises quoi pour y avoir acces ? Pour consulter, modifier...
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 : |
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?
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`)
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.
Marsh Posté le 22-04-2003 à 12:44:12
toutoun88 a écrit : |
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.
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 +
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?
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?
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.
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.
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