2010-11-23 4 views
2

Je vais avoir du mal à obtenir de meilleurs résultats sur cette requête:mal l'optimisation d'une requête

Je les 2 tableaux suivants:

DROP TABLE IF EXISTS `casino`.`mutualfriends`; 
CREATE TABLE `casino`.`mutualfriends` (
    `CustUID` varchar(64) CHARACTER SET ascii NOT NULL, 
    `CustUID2` varchar(64) CHARACTER SET ascii NOT NULL, 
    `FType` tinyint(4) NOT NULL, 
    PRIMARY KEY (`CustUID`,`CustUID2`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 


DROP TABLE IF EXISTS `casino`.`customers`; 
CREATE TABLE `casino`.`customers` (
    `CustFullName` varchar(45) NOT NULL, 
    `CustEmail` varchar(128) NOT NULL, 
    `CustUID` varchar(64) CHARACTER SET ascii NOT NULL, 
    `CustMoney` bigint(20) NOT NULL DEFAULT '0', 
    `SmallPicURL` varchar(120) CHARACTER SET ascii DEFAULT '', 
    `LargePicURL` varchar(120) CHARACTER SET ascii DEFAULT '', 
    PRIMARY KEY (`CustUID`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Le tableau des clients a des lignes 1M, des amis communs a 500K lignes. J'ai du mal à optimiser cette requête; il semble qu'il y ait une numérisation de table en l'utilisant. Je voudrais minimiser l'analyse:

SELECT c.CustUID AS Cuid, c.CustFullName, c.CustMoney, c.SmallPicURL 
FROM `customers` c 
WHERE c.`CustUID` = '1:1542073175' 
UNION 
SELECT m.`CustUID2` AS Cuid, c.CustFullName, c.CustMoney, c.SmallPicURL 
FROM `mutualfriends` m, `customers` c 
WHERE m.`CustUID` = '1:1542073175' 
AND c.`CustUID` = m.`CustUID2` 
UNION 
SELECT m.`CustUID` AS Cuid, c.CustFullName, c.CustMoney, c.SmallPicURL 
FROM `mutualfriends` m, customers c 
WHERE m.`CustUID2` = '1:1542073175' 
AND c.CustUID = m.`CustUID` 
+0

qu'est-ce que vous essayez exactement de faire? Essayez-vous d'obtenir une liste de tous les clients et de leurs amis communs? Ce n'est pas très clair avec votre code. – Ramy

+0

Eh bien, ce que je fais est d'obtenir une liste de clients qui sont des amis communs avec un client dont son identifiant est: «1: 1542073175». les résultats de la requête sont corrects, mais ses performances sont médiocres, je cherche un moyen d'obtenir les mêmes résultats que la requête ci-dessus mais avec de meilleures performances – mysqldude

Répondre

2

Je pense que vous avez besoin d'un index sur MutualFriends.CustUID2 (un index de doublons, pas un index unique, et non dans le cadre de la clé primaire). La clé primaire vous donne probablement un index utilisable pour les requêtes où le client identifié ('1: 1542073175') est listé en premier.

Vérifiez l'explication du plan de requête.

Je pense que vous avez raison qu'il ya une analyse séquentielle pour la troisième partie de l'Union, et peut-être le deuxième aussi.

+1

Je suis d'accord. Consultez http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html, en particulier la partie sur les index à plusieurs colonnes. – Mike

+0

mais quelle serait ma clé primaire? – mysqldude

+0

@mysqldude: Votre clé primaire est bien - la combinaison de CustUID et CustUID2 est unique (bien que l'on puisse dire que si vous avez CustUID = 1 et CustUID2 = 2, vous ne devriez pas avoir aussi une entrée CustUID = 2 et CustUID2 = 1, mais la clé primaire n'applique pas cela). Vous avez juste besoin d'un index supplémentaire sur CustUID2 qui n'est pas une clé primaire (bien que ce soit une clé étrangère à la table Customers). Il doit s'agir d'un index non unique (doublons) puisque la même personne peut se lier d'amitié avec de nombreuses personnes (en plus de se lier d'amitié avec de nombreuses personnes). La colonne CustUID doit également être déclarée comme clé étrangère. –

0

essayer cette requête

SELECT c.CustUID AS Cuid, c.CustFullName, c.CustMoney, c.SmallPicURL 
FROM `customers` c INNER JOIN `mutualfriends` m 
IN c.CustUID = m.`CustUID` 
WHERE m.`CustUID2` = '1:1542073175' 
+0

merci pour la réponse, ça ne donne pas les mêmes résultats que ma requête, des rangées, des idées? – mysqldude

+1

La requête ne sélectionne pas correctement. Si le client n'a pas d'amis communs, rien n'est sélectionné; si le client n'est pas un ami commun avec lui-même, alors rien n'est sélectionné; il ne sélectionne pas les lignes où le client est l'ami principal de quelqu'un d'autre; –

+0

ouais j'ai besoin de cette partie où le client est un ami de quelqu'un d'autre. cette requête ne couvre qu'un côté du problème, quand je UNION de l'autre côté l'analyse de la table montre à nouveau: | – mysqldude

0

Essayez avec cette requête:

select * 
from customers 
where CustUID in (
    select CustUID 
    from mutual_friends 
    where CustUID2 = '1:1542073175' 
    union all 
    select CustUID2 
    from mutual_friends 
    where CustUID = '1:1542073175' 
    union all 
    select '1:1542073175' 
) 

Est-ce que plus vite?

+0

qui analyse la table de tous les clients pour une raison quelconque: | – mysqldude