2013-03-25 10 views
7

Ho questa query che impiega circa 3,5 secondi solo per recuperare 2 record. Tuttavia ci sono oltre 100k righe nelle testimonianze, 13k negli utenti, 850 nei corsi, 2 negli esami.Dove sto sbagliando nell'usare un join nella query mysql - Spiega il risultato pubblicato anche

SELECT t.*, u.name, f.feedback 
FROM testmonials t 
INNER JOIN user u ON u.id = t.userid 
INNER JOIN courses co ON co.id = t.courseid 
LEFT JOIN exam ex ON ex.id = t.exam_id 
WHERE t.status = 4 
AND t.verfication_required = 'Y' 
AND t.verfication_completed = 'N' 
ORDER BY t.submissiondate DESC 

. Spiegare risultato:.

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE co ALL  PRIMARY  NULL NULL NULL 850  Using temporary; Using filesort 
1 SIMPLE t ref  CID,nuk_tran_user CID  4 kms.co.id 8 Using where 
1 SIMPLE u eq_ref PRIMARY  PRIMARY  4 kms.t.userid 1 Using where 
1 SIMPLE ex eq_ref PRIMARY  PRIMARY  3 kms.t.eval_id 1 

Se rimuovo la tabella courses uniscono quindi la query restituisce il risultato piuttosto veloce. Non riesco a capire perché questa query deve selezionare tutte le righe dei corsi, ad esempio 850?

Qualche idea su cosa sto facendo male?

Modifica: Ho un indice su courseid, userid nella tabella di testimonianze e queste sono le chiavi primarie delle rispettive tabelle.

EDIT 2

ho appena rimosso l'indice courseid dalla tabella testimonianze (solo per testare) ed è interessante la query restituito risultati 0.22 secondi !!! ?? Tutto il resto come sopra ha solo rimosso solo questo indice.

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE t ALL  nuk_tran_user NULL NULL NULL 130696 Using where; Using filesort 
1 SIMPLE u eq_ref PRIMARY  PRIMARY  4 kms.t.userid 1 Using where 
1 SIMPLE co eq_ref PRIMARY  PRIMARY  4 kms.t.courseid 1 
1 SIMPLE ex eq_ref PRIMARY  PRIMARY  3 kms.t.exam_id 1 

EDIT 3

EDIT 3

CREATE TABLE IF NOT EXISTS `courses` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    `description` text NOT NULL, 
    `duration` varchar(100) NOT NULL DEFAULT '', 
    `objectives` text NOT NULL, 
    `updated_at` datetime DEFAULT NULL, 
    `updated_by` int(10) unsigned DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=851 ; 


Testimonials 


CREATE TABLE IF NOT EXISTS `testimonials` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `feedback` text NOT NULL, 
    `userid` int(10) unsigned NOT NULL DEFAULT '0', 
    `courseid` int(10) unsigned NOT NULL DEFAULT '0', 
    `eventid` int(10) unsigned NOT NULL DEFAULT '0', 
    `emr_date` datetime DEFAULT NULL, 
    `exam_required` enum('Y','N') NOT NULL DEFAULT 'N', 
    `exam_id` smallint(5) unsigned NOT NULL DEFAULT '0', 
    `emr_completed` enum('Y','N') NOT NULL DEFAULT 'N', 
    PRIMARY KEY (`id`), 
    KEY `event` (`eventid`), 
    KEY `nuk_tran_user` (`userid`), 
    KEY `emr_date` (`emr_date`), 
    KEY `courseid` (`courseid`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=134691 ; 

.. Questo è l'ultimo risultato della query Spiega ora ...

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE t ALL  nuk_tran_user,courseid NULL NULL NULL 130696 Using where; Using filesort 
1 SIMPLE u eq_ref PRIMARY  PRIMARY  4 kms.t.userid 1 Using where 
1 SIMPLE co eq_ref PRIMARY  PRIMARY  4 kms.t.courseid 1 
1 SIMPLE ex eq_ref PRIMARY  PRIMARY  3 kms.t.exam_id 1 
+1

hai un indice su 'courses.ID'? –

+0

sì ha indice nella tabella delle testimonianze ed è una chiave primaria della tabella dei corsi. – user1421214

+0

Perché non sembra che tu abbia ... –

risposta

0

Potresti dare una prova al seguente query al posto dell'originale:

SELECT t.*, u.name, f.feedback 
FROM testmonials t 
INNER JOIN user u ON u.id = t.userid 
LEFT JOIN exam ex ON ex.id = t.exam_id 
WHERE t.status = 4 
AND t.verfication_required = 'Y' 
AND t.verfication_completed = 'N' 
AND t.courseid in (SELECT co.id FROM courses co) 
ORDER BY t.submissiondate DESC 

Devi selezionare le colonne dalla tabella dei corsi?

1

Effettuare un ordine BY che non ha un indice corrispondente che può essere utilizzato causa problemi di ritardo. Anche se questo non risponde in modo specifico al tuo problema della tabella dei corsi.

La query originale sembra PIÙ OK, ma si fa riferimento a "f.feedback" e non vi è alcun alias "f" nella query. Ti riferisci anche a "verification_required" e "verification_completed" ma non vedi quelli nelle strutture della tabella ma trova "exam_required" e "emr_completed".

Vorrei tuttavia cambiare una cosa. Nella tabella testimonianze, invece di singoli indici di colonna, vorrei aggiungere un altro con più colonne sia per approfittare della query più criteri e l'ordine da

create table ... 
KEY StatVerifySubmit (status, verification_required, verification_completed, submissionDate) 

ma appare la query si riferisce alle colonne non elencate la struttura della tabella, ma potrebbe invece essere

KEY StatVerifySubmit (status, exam_required, emr_completed, emr_Date)