2011-06-28 13 views
0

高トラフィックのウェブサイトで過去6ヶ月にわたり多くの悲しみを引き起こしていたクエリの助けが切望されています。私は単純なSQLクエリを書くことができるフロントエンドの開発者ですので、この問題を自分で修正することはできません。このクエリでは、メモリやCPUが不足していることや、VPS上の他のクエリからの干渉を頻繁に検出してmysqlデータベースを頻繁にロックしています。私はハードウェアをアップグレードしたが、それだけでは問題は解決しなかった。ここでは、クエリが何をしようとしているのかについての説明を示します。SQLクエリの最適化に関するヘルプが必要

ユーザーは特定のURL(例:the_source_url)にアクセスします。アプリケーションは、他のユーザー(the_source_urlにもアクセスしているユーザー)が最も早くアクセスし、最も頻繁にアクセスされ、最も頻繁にアクセスされないものから順にアクセスした関連するsource_urlsを取得しようとします。基本的に、アプリケーションは、同様の関心のあるユーザーを見つけようとしており、以前にアクセスした他のページを表示しています。

これは私が愚か/若かったとウェブサイトは、トラフィックがなかったときに私が書いた「複雑なクエリ」です:

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
    FROM topsources 
WHERE SOURCE_URL <> ? 
    AND USER_ID IN (SELECT DISTINCT(USER_ID) 
        FROM topsources WHERE SOURCE_URL = ?) 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC 

これは、テーブルの構造である:

`topsources` (
    `USER_ID` varchar(255) NOT NULL, 
    `DATE_AND_HOUR` varchar(255) NOT NULL, 
    `UPDATED_TIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `ITEM_ID` int(11) NOT NULL, 
    `SOURCE_URL` varchar(100) NOT NULL, 
    `FEED_PAGE_URL` varchar(255) NOT NULL, 
    `CATEGORY_URL` varchar(100) NOT NULL, 
    `REFERRER` varchar(2048) DEFAULT NULL, 
    PRIMARY KEY (`USER_ID`,`DATE_AND_HOUR`(30),`ITEM_ID`), 
    KEY `USER_ID` (`USER_ID`), 
    KEY `FEED_PAGE_URL` (`FEED_PAGE_URL`), 
    KEY `SOURCE_URL` (`SOURCE_URL`), 
    KEY `CATEGORY_URL` (`CATEGORY_URL`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

ことに注意してください。私は既にサブセレクトの代わりに内部結合を試みましたが、それはうまくいきません。つまり、以下のクエリは、上記のクエリと同じ結果を返しません。

​​3210
+0

GROUP BYを使用するときはDISTINCTを使用しないでください。 – niktrs

答えて

4

IN副選択がMySQLで最適化されていません。 subselectを実行してからoutser selectを実行する代わりに、MySQLは外側の選択と一致する各行に対して副選択を実行します。このため、IN句の副選択は結合で置き換える必要があります。クエリの高速バージョンは次のとおりです。

SELECT DISTINCT(SOURCE_URL), COUNT(SOURCE_URL) CATCOUNT 
FROM topsources 
INNER JOIN 
(SELECT DISTINCT(USER_ID) 
       FROM topsources WHERE SOURCE_URL = ?) as t 
ON (topsources.USER_ID = t.USER_ID) 
WHERE SOURCE_URL <> ? 
GROUP BY SOURCE_URL ORDER BY CATCOUNT DESC 
+1

上記のコードは、MySQLが元のクエリまたは改善案をどのように解釈するかの例ですか? –

+0

慎重に読んでください:IN節のsubselectsは、MySQLが副選択を扱う方法(前述)のために、結合で置き換えなければなりません。したがって、書き換えられたクエリは改善提案されています –

+0

申し訳ありませんが、私は失礼であることを意味していませんでした。もともとあなたが伝えようとしていたことがわかりませんでした。それをクリアしていただきありがとうございます。 –

1

これは標準化のために叫んでいます。何が本当に必要なの

id | url_id 
1 | 1 

次に、あなたのDISTINCT(url_id)あなたのtopsourcesテーブルで次に

id | url 
1 | http://.... 

のようなURLテーブル大幅に高速であるべきです。