2013-04-26 8 views
1

У нас проблема с одним из наших операторов MySQL.MySQL Присоединиться очень медленно

В основном, следующий оператор занимает 5 секунд. Мы поставили диагноз , это связано с объединением двух операторов select. Когда операторы выбора работают индивидуально, они занимают всего 0,2 секунды, но в сочетании с JOIN он занимает 5 секунд.

Есть ли что-нибудь, что вы можете видеть, что мы делаем неправильно или вы можете увидеть лучший способ ?

Индексы были добавлены ко всем столбцам, содержащихся в соединении, но это не влияет со скоростью

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` 

определения таблицы:

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; 

данных для одного предмета походного выглядит следующим образом - заказ 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 

требуемый выход:

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

Большое спасибо

принять это шаг вперед ... что если q_1 и q_4 были в двух отдельных таблицах. например, следующую структуру таблицы. Единственный способ, которым я могу думать, это добавить левые внешние соединения и несколько подзапросов?

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

Может помочь, если мы увидим вашу базу данных struture и некоторые строки примеров. –

+0

Pl опубликует структуру таблицы и объяснение. – Meherzad

+0

Да, мы находимся в процессе изучения того, является ли это наиболее оптимальной структурой таблицы. По сути, это большая таблица без реляционных подключений. Существует таблица, в которой хранятся первичные ключи, которые относятся к строкам во второй таблице. Затем он собирает все данные, относящиеся к одному объекту (субъекту), затем собирает все данные, относящиеся ко второму объекту (testoccasion), затем объединяет его все вместе. – user2324001

ответ

0

Попробуйте этот запрос,

Вы создаете второй внутренний запрос, который не имеет смысла. было бы лучше удалить этот.

Создание этих индексов таблицы questions_1_100 индекса compund (primaryid, q_1, q_4)

primarys таблицы индекса (primaryid)

Надеется, что это помогает ..

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

Я создал составной индекс и запустил обновленный запрос, и, к сожалению, это заняло гораздо больше времени. Его около 30 секунд и до сих пор считая :) – user2324001

+0

вы можете опубликовать объяснение вашего запроса после обновленных индексов. – Meherzad

0

Try:

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.

Более простой вариант, с тестовым случаю 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

Привет, спасибо за код, это имеет большой смысл, хотя он возвращает пустой набор, тогда как другой код возвращается тысячи строк. Я не вижу, что отличает это, чтобы вернуть пустой набор – user2324001

+0

@ user2324001: Попробуйте второй запрос в моем обновленном ответе. –

+0

Привет, Марк, спасибо за вашу помощь. Первый запрос возвращает emptyset, в то время как второй действительно получает данные чрезвычайно быстрыми, хотя столбец studynumbers равен – user2324001

Смежные вопросы