2012-07-05 18 views
5

私のmysqlデータベースは、特に低速なクエリを実行しようとCPUを使いたくなっています。私が説明をするとき、mysqlは "whereを使う、一時的に使う、filesortを使う"と言っています。このパズルを解読し解決するのを助けてください。ヘルプのチューニングSQLクエリ

表構造:

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

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

は、このクエリを改善する方法はありますか?また、CPUの負荷を軽減するのに役立つmysqlの設定はありますか?私は私のサーバーで利用可能なメモリをさらに割り当てることができます。トリックを行う必要があります

+1

をtopsources.USER_ID =「XXXX」THEN 1つのELSE 0 END)= 0この部分は、私は私が – Jester

+0

これよりよく行う方法を考えてみましょう考える最も問題ですクエリを実行していますか? –

+0

は、更新があなたながら起こっている説明から、それは正確な出力を掲示するのに役立つだろう –

答えて

0

私は、SQLの変更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

このクエリは異なる結果セットを返します。元のクエリと同じではありません。 – Zero

+0

クエリが更新されましたpls – Jester

1

これを読めば、クエリを助けるために最も可能性が高いことは、それが多くの値を取る場合は特に、CATEGORY_SLUGのインデックスです。 (すなわち、クエリが高度に選択的である場合)。クエリは結果を得るためにテーブル全体を読み取る必要がありますが、10秒は長時間かかるようですが。

私は、HAVING句は、クエリ処理に影響を与えることになるとは思いません。

問合せは、行にちょうど限り、あなたはそれを実行する場合は2回かかりますか?

+0

既にCATEGORY_SLUGにインデックスがあります。上記の表の構造をお読みください。クエリはほとんどの場合、実行に時間がかかります。 – Zero

+0

Hmmm、いくつのカテゴリのスラグがありますか?場合によっては、ほんの一握りの値しかないときに、インデックスが良いよりも害を及ぼすことがあります。 –

+0

未満100匹のカテゴリナメクジ。 – Zero

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

クエリは、私はその行を削除する場合は「WHERE句」 – Zero

+0

、このクエリが返すの彼のラインを削除 'とts.SOURCE_SLUG = TS2.SOURCE_SLUG' – jared

+0

に不明な列「TS2.SOURCE_SLUG」を返すために、それはインデックスを使用することはできません空の結果セット – Zero

0

あなただけのデータで自分のクエリを投げることはできませんが、私はそれを自分でやっていたならば、これは私の最初の試みになるときに何かを最適化することは常に難しい:

MAX(CASE HAVING
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;