需要帮助调优sql查询

时间:2012-07-05 18:00:30

标签: mysql sql performance

我的mysql数据库已经变得CPU饥饿,试图执行一个特别慢的查询。当我做一个解释时,mysql说“使用where;使用临时;使用filesort”。请帮助破译和解决这个难题。

表格结构:

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;

该表有370K行...有时更高。以下查询需要10秒以上。

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;

以下是扩展说明:

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

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

有没有办法改进此查询?此外,是否有任何mysql设置可以帮助减少CPU负载?我可以分配更多可在我的服务器上使用的内存。

4 个答案:

答案 0 :(得分:1)

最有可能帮助查询的是CATEGORY_SLUG上的索引,特别是如果它采用了许多值。 (也就是说,如果查询具有高度选择性。)查询需要读取整个表以获得结果 - 尽管10秒似乎很长时间。

我认为HAVING子句不会影响查询处理。

如果你连续两次运行它,查询的时间是否也一样长?

答案 1 :(得分:0)

如果我读到这个我的sql更改正确

那应该可以解决问题
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;

答案 2 :(得分:0)

如果有很多行符合您的CATEGORY_SLUG标准,可能很难快速实现,但这会更快吗?

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;

答案 3 :(得分:0)

当你不能自己对数据进行查询时,总是难以优化某些东西,但如果我自己这样做,这将是我的第一次尝试:

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;
相关问题