2012-07-05 13 views
5

Mi base de datos mysql se ha convertido en una CPU hambrienta que intenta ejecutar una consulta especialmente lenta. Cuando hago una explicación, mysql dice "Using where; Using temporary; Using filesort". Por favor ayuda a descifrar y resolver este rompecabezas.Necesita ayuda para sintonizar la consulta sql

Estructura de tabla:

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 tabla tiene 370K filas ... A veces superior. La consulta a continuación toma más de 10 segundos.

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; 

aquí está el extendieron explicar:

+----+-------------+------------+------+---------------+---------------+---------+-------+--------+----------+----------------------------------------------+ 
| 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 | 
+----+-------------+------------+------+---------------+---- 

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

¿Hay alguna manera de mejorar esta consulta? Además, ¿hay alguna configuración de mysql que pueda ayudar a reducir la carga de la CPU? Puedo asignar más memoria disponible en mi servidor.

+1

HAVING MAX (CASO CUANDO topsources.USER_ID = 'xxxx' THEN 1 ELSE 0 END) = 0 esta parte es la más problemática Creo que déjame pensar cómo hacerlo mejor – Jester

+0

ayudaría a publicar la salida exacta de la explicación –

+0

Están ocurriendo actualizaciones mientras están ejecutando la consulta? –

Respuesta

0

Que debe hacer el truco si leo esta alteración mi sql registrado correctamente

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

Esta consulta devuelve un conjunto de resultados diferente. No es lo mismo que la consulta original. – Zero

+0

Actualizada la consulta intente por favor pls – Jester

1

Lo más probable que ayude a la consulta es un índice en CATEGORY_SLUG, sobre todo si se toma en muchos valores. (Es decir, si la consulta es altamente selectiva). La consulta necesita leer toda la tabla para obtener los resultados, aunque 10 segundos parece mucho tiempo.

No creo que la cláusula HAVING afecte el procesamiento de consultas.

¿La consulta toma el mismo tiempo si la ejecuta dos veces seguidas?

+0

Ya hay un índice en CATEGORY_SLUG. Por favor, lea la estructura de la tabla de arriba. Las consultas casi siempre demoran más en ejecutarse. – Zero

+0

Hmmm, ¿Cuántas babosas de categoría hay? A veces, los índices hacen más daño que bien, especialmente cuando solo hay un puñado de valores. –

+0

Menos de 100 babosas de categoría. – Zero

0

Si hay muchas filas que coinciden con sus criterios CATEGORY_SLUG, puede ser difícil hacerlo rápido, pero ¿es esto más rápido?

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

Consulta devuelve Columna desconocida 'TS2.SOURCE_SLUG' en 'where clause' – Zero

+0

eliminar su línea 'AND ts.SOURCE_SLUG = TS2.SOURCE_SLUG' – jared

+0

Si elimino esa línea, esta consulta devuelve conjunto de resultados vacíos – Zero

0

siempre difícil de optimizar algo cuando no se puede simplemente tirar consultas a los datos usted mismo, pero esto sería mi primer intento, si lo estaba haciendo a mí mismo:

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; 
Cuestiones relacionadas