2012-07-05 16 views
5

Il mio DB mysql è diventato affamato di CPU che tenta di eseguire una query particolarmente lenta. Quando faccio una spiegazione, mysql dice "Using where; Using temporary; Using filesort". Aiutateci a decifrare e risolvere questo enigma.Hai bisogno di aiuto per l'ottimizzazione della query sql

Struttura della tabella:

CREATE TABLE `topsources` (
    `USER_ID` varchar(255) NOT NULL, 
    `UPDATED_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `URL_ID` int(11) NOT NULL, 
    `SOURCE_SLUG` varchar(100) NOT NULL, 
    `FEED_PAGE_URL` varchar(255) NOT NULL, 
    `CATEGORY_SLUG` varchar(100) NOT NULL, 
    `REFERRER` varchar(2048) DEFAULT NULL, 
    PRIMARY KEY (`USER_ID`,`URL_ID`), 
    KEY `USER_ID` (`USER_ID`), 
    KEY `FEED_PAGE_URL` (`FEED_PAGE_URL`), 
    KEY `SOURCE_SLUG` (`SOURCE_SLUG`), 
    KEY `CATEGORY_SLUG` (`CATEGORY_SLUG`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

La tabella ha 370K righe ... a volte superiore. La query seguente richiede 10+ secondi.

SELECT topsources.SOURCE_SLUG, COUNT(topsources.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources 
WHERE CATEGORY_SLUG = '/newssource' 
GROUP BY topsources.SOURCE_SLUG 
HAVING MAX(CASE WHEN topsources.USER_ID = 'xxxx' THEN 1 ELSE 0 END) = 0 
ORDER BY VIEW_COUNT DESC; 

Ecco il esteso spiegare:

+----+-------------+------------+------+---------------+---------------+---------+-------+--------+----------+----------------------------------------------+ 
| id | select_type | table  | type | possible_keys | key   | key_len | ref | rows | filtered | Extra          | 
+----+-------------+------------+------+---------------+---------------+---------+-------+--------+----------+----------------------------------------------+ 
| 1 | SIMPLE  | topsources | ref | CATEGORY_SLUG | CATEGORY_SLUG | 302  | const | 160790 | 100.00 | Using where; Using temporary; Using filesort | 
+----+-------------+------------+------+---------------+---- 

----------- + --------- + ------- + - ------- + ---------- + ------------------------------- --------------- +

C'è un modo per migliorare questa query? Inoltre, ci sono impostazioni mysql che possono aiutare a ridurre il carico della CPU? Posso allocare più memoria disponibile sul mio server.

+1

AVERE MAX (CASO QUANDO topsources.USER_ID = 'xxxx' allora 1 altrimenti 0 END) = 0 questa parte è la più problematica credo fammi pensare come fare questo meglio – Jester

+0

che sarebbe aiutano a inviare l'output esatto dalla spiegano –

+0

di aggiornamenti accadendo mentre si stanno eseguendo la query? –

risposta

0

Questo dovrebbe fare il trucco se ho letto questo mio sql alterazione correcty

SELECT topsources.SOURCE_SLUG, COUNT(topsources.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources 
WHERE CATEGORY_SLUG = '/newssource' and 
    topsources.SOURCE_SLUG not in (
     select distinct SOURCE_SLUG 
     from topsources 
     where USER_ID = 'xxxx' 
     ) 
GROUP BY topsources.SOURCE_SLUG 
ORDER BY VIEW_COUNT DESC; 
+0

Questa query restituisce un set di risultati diverso. Non è uguale alla query originale. – Zero

+0

Hai aggiornato la query prova che pls – Jester

1

La cosa più probabile per aiutare la query è un indice su CATEGORY_SLUG, soprattutto se assume molti valori. (Ovvero, se la query è altamente selettiva.) La query deve leggere l'intera tabella per ottenere i risultati, anche se 10 secondi sembrano lunghi.

non credo che la clausola HAVING sarebbe interessando l'elaborazione delle query.

Vuol la query prende basta che se lo si esegue due volte di fila?

+0

C'è già un indice su CATEGORY_SLUG. Si prega di leggere la struttura della tabella sopra. La query richiede quasi sempre più tempo per l'esecuzione. – Zero

+0

Hmmm, quante lumache di categoria ci sono? A volte, gli indici fanno più male che bene, soprattutto quando ci sono solo una manciata di valori. –

+0

Meno di 100 lumache di categoria. – Zero

0

Se ci sono molte righe con i tuoi criteri CATEGORY_SLUG, può essere difficile fare questo veloce, ma è presente qualsiasi più veloce?

SELECT ts.SOURCE_SLUG, COUNT(ts.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources ts 
WHERE ts.CATEGORY_SLUG = '/newssource' 
    AND NOT EXISTS(SELECT 1 FROM topsources ts2 
       WHERE ts2.CATEGORY_SLUG = '/newssource' 
        AND ts.SOURCE_SLUG = TS2.SOURCE_SLUG 
        AND ts2.USER_ID = 'xxxx') 
GROUP BY ts.SOURCE_SLUG 
ORDER BY VIEW_COUNT DESC; 
+0

Query restituisce Colonna sconosciuta 'TS2.SOURCE_SLUG' in 'clausola' – Zero

+0

rimuovere la sua riga 'AND ts.SOURCE_SLUG = TS2.SOURCE_SLUG' – jared

+0

Se rimuovo la riga, questa query restituisce set di risultati vuoto – Zero

0

sempre difficile ottimizzare qualcosa quando non si può semplicemente gettare le query i dati da soli, ma questo sarebbe stato il mio primo tentativo se stavo facendo io stesso:

SELECT t.SOURCE_SLUG, COUNT(t.SOURCE_SLUG) AS VIEW_COUNT 
FROM topsources t 
LEFT JOIN (
    SELECT SOURCE_SLUG 
    FROM topsources t 
    WHERE CATEGORY_SLUG = '/newssource' 
    AND USER_ID = 'xxx' 
    GROUP BY .SOURCE_SLUG 
) x USING (SOURCE_SLUG) 
WHERE t.CATEGORY_SLUG = '/newssource' 
AND x.SOURCE_SLUG IS NULL 
GROUP BY t.SOURCE_SLUG 
ORDER BY VIEW_COUNT DESC; 
Problemi correlati