2013-04-26 5 views
1

Nous avons un problème avec l'un de nos déclarations MySQL.MySQL Rejoignez très lent

En fait la déclaration suivante prend 5 secondes pour exécuter. Nous avons diagnostiqué il est tombé à la jointure de deux instruction select. Lorsque les instructions select sont individuellement, ils prennent terme que de 0,2 secondes, mais lorsqu'il est combiné avec le REJOIGNEZ-il prend 5 secondes.

Est-ce que vous pouvez voir que nous faisons mal ou pouvez-vous voir une meilleure façon ?

Les indices ont été ajoutés à toutes les colonnes contenues dans la jointure, mais il n'a pas d'effet la vitesse

SELECT temp_4.primaryid, temp_1.`subjectID` , temp_4.`testOccasionID` 
,`studyNumbers` ,`testDate` 

FROM (
    SELECT * FROM (
    SELECT primarys.primaryid , q_1 AS `subjectID` , q_2 AS `studyNumbers` FROM 
primarys LEFT OUTER JOIN questions_1_100 ON primarys.primaryid = 
questions_1_100.primaryid WHERE 0 = 0 AND q_1 IS NOT NULL GROUP BY primaryid) AS 
maintable_1 
GROUP BY `subjectID`) AS temp_1 

JOIN 

(SELECT * FROM 
(SELECT primarys.primaryid , q_1 AS `subjectID` , q_4 AS `testOccasionID` , 
DATE_FORMAT(q_5, '%m/%d/%Y') AS `testDate` FROM primarys LEFT OUTER JOIN 
questions_1_100 ON primarys.primaryid = questions_1_100.primaryid WHERE 0 = 0 AND 
q_1 IS NOT NULL AND q_4 IS NOT NULL GROUP BY primaryid) AS maintable_4 
GROUP BY `subjectID` ,`testOccasionID`) AS temp_4 

ON temp_1.`subjectID` = temp_4.`subjectID` 

Tableau définitions:

CREATE TABLE primarys 
(primaryid BIGINT(20) NOT NULL AUTO_INCREMENT, 
    dateinserted DATETIME, 
    datemodified DATETIME, 
    useridinserted BIGINT(20), 
    useridmodified BIGINT(20), 
    locked VARCHAR(1) NOT NULL DEFAULT 0, 
    primaryquestionlinks TEXT, 
    PRIMARY KEY (primaryid), 
    FOREIGN KEY (useridinserted) REFERENCES users (userid) ON UPDATE CASCADE ON DELETE SET NULL, 
    FOREIGN KEY (useridmodified) REFERENCES users (userid) ON UPDATE CASCADE ON DELETE SET NULL) ENGINE=InnoDB; 

CREATE TABLE questions_1_100 
(primaryid BIGINT(20) NOT NULL, 
    q_1 BIGINT(20), 
    q_2 VARCHAR(50), 
    q_3 BIGINT(20), 
    q_4 BIGINT(20), 
    q_5 DATE, 
    PRIMARY KEY (primaryid), 
    FOREIGN KEY (primaryid) REFERENCES primarys (primaryid) ON UPDATE CASCADE ON DELETE CASCADE) ENGINE=InnoDB; 

données pour un sujet unique marching est la suivante - la ordre est primaryid, q_1, Q_2, Q_4, q_5:

1 1 01001 NULL NULL 
7286 1 NULL  1  1997-12-18 
7287 1 NULL  2  1998-02-25 

la puissance requise est:

7286 1 01001 1  1997-12-18 
7287 1 01001 2  1998-02-25 

Un grand merci

de prendre un peu plus loin ... si q_1 et Q_4 étaient dans deux tableaux distincts. tels que la structure de table suivante. La seule façon dont je peux penser est d'ajouter des jointures externes gauche et plusieurs sous-requêtes?

CREATE TABLE primarys 
(primaryid BIGINT(20) NOT NULL AUTO_INCREMENT, 
PRIMARY KEY (primaryid)); 

CREATE TABLE questions_1_100 
(primaryid BIGINT(20) NOT NULL, 
q_1 BIGINT(20), 
q_2 VARCHAR(50), 
PRIMARY KEY (primaryid)); 

CREATE TABLE questions_101_200 
(primaryid BIGINT(20) NOT NULL, 
q_4 BIGINT(20), 
q_5 DATE, 
PRIMARY KEY (primaryid)); 

INSERT INTO primarys values (1); 
INSERT INTO primarys values (7286); 
INSERT INTO primarys values (7287); 

INSERT INTO questions_1_100 VALUES (1,'1','01001'); 
INSERT INTO questions_1_100 VALUES (7286,'1',''); 
INSERT INTO questions_1_100 VALUES (7287,'1',''); 

INSERT INTO questions_101_200 VALUES (7286,'1','1997-12-18'); 
INSERT INTO questions_101_200 VALUES (7287,'2','1998-02-25'); 
+3

Peut-être utile si nous pouvions voir votre base de données et quelques lignes d'exemple. –

+0

Postez la structure de la table et expliquez la déclaration .. – Meherzad

+0

Oui, nous sommes en train de nous demander si c'est la structure de table la plus optimale. Essentiellement, c'est une grande table sans connexion relationnelle. Il y a une table qui contient les clés primaires qui font référence aux lignes de la seconde table. Il recueille alors toutes les données relatives à un objet (sujet) puis recueille toutes les données relatives à un deuxième objet (testoccasion) puis les combine toutes ensemble. – user2324001

Répondre

0

Essayez cette requête

Vous créez deuxième requête interne qui est d'aucune utilité. il vaudrait mieux enlever celui-là.

Créer ces indices tableau questions_1_100 index compund (primaryid, q_1, Q_4)

table d'index primarys (de primaryid)

Hope this helps ..

SELECT 
    temp_4.primaryid, 
    temp_1.`subjectID` , 
    temp_4.`testOccasionID` , 
    `studyNumbers` , 
    `testDate` 
FROM (
    SELECT 
    primarys.primaryid , 
    q_1 AS `subjectID` , 
    q_2 AS `studyNumbers` 
    FROM 
    primarys 
    LEFT OUTER JOIN 
    questions_1_100 
    ON 
    primarys.primaryid = questions_1_100.primaryid 
    WHERE 
    q_1 IS NOT NULL 
    GROUP BY 
    primaryid, 
    subjectID) AS temp_1 
JOIN 
    (SELECT 
    primarys.primaryid , 
    q_1 AS `subjectID` , 
    q_4 AS `testOccasionID` , 
    DATE_FORMAT(q_5, '%m/%d/%Y') AS `testDate` 
    FROM 
    primarys 
    LEFT OUTER JOIN 
    questions_1_100 
    ON 
    primarys.primaryid = questions_1_100.primaryid 
    WHERE 
    q_1 IS NOT NULL AND 
    q_4 IS NOT NULL 
    GROUP BY 
    primaryid, 
    subjectID, 
    testOccasionID) AS temp_4 
ON 
    temp_1.`subjectID` = temp_4.`subjectID` 
+0

J'ai créé l'index composé et exécuter la requête mise à jour et, malheureusement, il a fallu beaucoup plus de temps. C'est environ 30 secondes et toujours compter :) – user2324001

+0

pouvez-vous poster expliquer de votre requête après les index mis à jour .. – Meherzad

0

Essayez:

SELECT p.primaryid , 
     q2.q_1 AS `subjectID`, 
     q4.q_4 AS `testOccasionID`, 
     q2.q_2 AS `studyNumbers`, 
     DATE_FORMAT(q4.q_5, '%m/%d/%Y') AS `testDate` 
FROM primarys p 
JOIN questions_1_100 q2 
    ON p.primaryid = q2.primaryid 
JOIN questions_1_100 q4 
    ON q2.q_1 = q4.q_1 and q4.q_4 is not null 

SQLFiddle here.

Une version plus simple, à l'occasion d'essai primaryid:

SELECT q4.primaryid , 
     q2.q_1 AS `subjectID`, 
     q4.q_4 AS `testOccasionID`, 
     q2.q_2 AS `studyNumbers`, 
     DATE_FORMAT(q4.q_5, '%m/%d/%Y') AS `testDate` 
FROM questions_1_100 q2 
JOIN questions_1_100 q4 
    ON q2.q_1 = q4.q_1 and q4.q_4 is not null 
where q2.q_2 is not null 

SQLFiddle here.

+0

Salut, merci pour le code, cela fait beaucoup de sens, mais il retourne un ensemble vide alors que l'autre code renvoie des milliers de lignes. Je ne peux pas voir quoi de différent qui le ferait retourner un ensemble vide – user2324001

+0

@ user2324001: Essayez la deuxième requête dans ma réponse mise à jour. –

+0

Salut Mark, Merci pour votre aide. La première requête renvoie un emptyset tandis que la seconde obtient les données extrêmement rapidement bien que la colonne studynumbers soit nulle. – user2324001