シンプルなMySQLのクエリが2時間以上かかる

だから、私は500万レコードのデータベースを持っており、質疑応答サイトの情報を保管しています。その構造は...

question, qid, quserid, answer, auserid;

(qidは質問のID番号です)

私は、特定のユーザが回答していない質問を持っているすべてのユーザを見つけようとしており、特定のユーザが答えなかった質問の量でソートしています。ここに私の質問です:

SELECT quserid, COUNT(quserid)
FROM `qanda` 
WHERE qid NOT IN (SELECT qid FROM `qanda` WHERE auserid='myusername' GROUP BY qid) 
GROUP BY quserid 
ORDER BY COUNT(quserid) DESC 
LIMIT 0,1000;

問題:それは2時間以上かかっており、時計はまだ離れている。誰もこのデータベースを高速化する方法を知っていますか?私はデータベースや何かにバグがあると思いますが、たいてい単純なクエリでは30秒しかかかりませんので、ちょっとばかげています。誰でも微調整を知っていますか?おそらく設定ファイルや何かに単純な変更?

..........

ここで私がコピーして貼り付けたデータベースのデータがあります。フォーマットが不十分で申し訳ありません。

you could have any one person in the entire wor... greendaystud    ive got the person i want...its great...because sh...  •glitter•rock•  191437  If you could have any one person in the entire wor...  just~another~slave2tears    i already got em
                            •glitter•rock•  191437  If you could have any one person in the entire wor...  korn_chick2007  matt or chris...i have feelings for them
                            •glitter•rock•  189555  why are you so sexy?
    just~another~slave2tears    my b/f says i am...i dun tink so tho
                            •glitter•rock•  189555  why are you so sexy?
    korn_chick2007  im not
                            •glitter•rock•  189555  why are you so sexy?
    MyKool-AidsSexy     i dont think i am
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe... death-tone  yip
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe... _doieverknowwhoiam_     you know whats weird? my friend sandy says that a ...
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe... Cute_Physco_kitty   Pretty much..
                            †brokengirl†    115228  If you are supposed to expect the unexpected,
doe... Leslie02    WHAT! OK, now im confused!
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor... death-tone  what's listerine?
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor... _doieverknowwhoiam_     i don't know, and maybe it's jut me bu...
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor... darksunofdeath  How old is the listerine pack?
                            †brokengirl†    114995  Why does my listerine taste like sausage this
mor... Cute_Physco_kitty   uhh...New brand of Listerine?
    †brokengirl†    114995  Why does my listerine taste like sausage this
mor... Leslie02    did you have sausage for breakfast?     †brokengirl†    104305  What should I name my pinky toe on my left
foot?¿...  death-tone  "Pinkytoe"        

そして、便利な列タイトルを使用して、期待される出力...

Questioner User ID | Number of questions asked by the Questioner that were unanswered by 'myuserid'

Greenbay Packer | 6
DollyDoll | 63
PsychoticPokemon | 62
HelloKitty | 61
GreenDayFan | 60

...

IDontAskManyQuestion | 2
WhatsAQuestion? | 1

EXPLAINの出力は次のとおりです

> mysql-> EXPLAIN
>     ->
>     -> SELECT quserid, COUNT(quserID)
>     -> FROM `qanda`
>     -> WHERE qid NOT IN (SELECT qid FROM `qanda` WHERE auserid='boxocereal' GROU P BY qid)
>     -> GROUP BY quserid
>     -> ORDER BY COUNT(quserid) DESC
>     -> LIMIT 0,1000;
> 

+----+--------------------+-------+------+---------------+------+---------+-----
> -+---------+----------------------------------------------+ | id | select_type        | table | type | possible_keys | key  | key_len |
> ref  | rows    | Extra                                        |
> +----+--------------------+-------+------+---------------+------+---------+-----
> -+---------+----------------------------------------------+ |  1 | PRIMARY            | qanda | ALL  | NULL          | NULL | NULL    |
> NULL  | 3167995 | Using where; Using temporary; Using filesort | |  2
> | DEPENDENT SUBQUERY | qanda | ALL  | NULL          | NULL | NULL    |
> NULL  | 3167995 | Using where; Using temporary; Using filesort |
> +----+--------------------+-------+------+---------------+------+---------+-----
> -+---------+----------------------------------------------+ 2 rows in set (0.02 sec)
> 
> mysql->
0
おそらく真実ではない@Interrobang ...本当に??
追加された 著者 McGarnagle,
@Interrobang私はMySqlが無料であると知っていますが、多分彼らはいくつかの開発者や何かを雇うためにお金を充電し始めるべきです...ちょうどスティーン '
追加された 著者 McGarnagle,
@ NathanCantos:必要に応じて INDEX を追加できますか?クエリを再実行します。インデックス作成を使用すると、クエリはより高速になります... こちら
追加された 著者 Fahim Parkar,
@ NathanCantos:確認していただきありがとうございます。
追加された 著者 Fahim Parkar,
@ NathanCantos:サンプルデータと期待される出力を提供できますか?それは本当に私たちを助けます。
追加された 著者 Fahim Parkar,
@ NathanCantos:こちらのサンプルデータを作成しました。これがいいのかどうか知らせてください。
追加された 著者 Fahim Parkar,
@ NathanCantos:サンプル入力で質問をフォーマットしてください。..
追加された 著者 Fahim Parkar,
どのようなインデックスがありますか?
追加された 著者 Jon Skeet,
あなたは既に参加を試みましたか?
追加された 著者 Gumbo,
MySQLは従属サブクエリの結果をキャッシュするほどスマートではありません。結果セットの行ごとに1回実行します。
追加された 著者 Interrobang,
@dbaseman yep: stackoverflow.com/questions/3417074/… あなたが好きなら、私は実際のマニュアルエントリを見つけることができます
追加された 著者 Interrobang,
テーブルは質問ごとに1行に1つずつ(つまり正規化されていない1対多の)多数の行を持つとしますか?
追加された 著者 Chris Trahey,
qanda は表かビューか?
追加された 著者 Chris Trahey,
<あなたの問い合わせ>は何を表していますか?スクリーンショットを投稿できますか?
追加された 著者 Ashwini Dhekane,
@ Fahim Parkar:サンプルデータはうまく見えます。
追加された 著者 Nathan Cantos,
@文章:はい、基本的にすべての行は一意の答えに対応しています。与えられた質問は複数の回答を持つことができるので、複数の行は1つの質問に「属する」ことができます。
追加された 著者 Nathan Cantos,
ちょうどすべての「セル」にはデータベースの価値があるため、索引付けにはメリンクのメリットがあります。そうではなくても、索引付けは0からの飛躍ではなく、線形10-20%の種類[O(1.2 * n)対O(1.0 * n) (n ^ 3)からO(n log n)のように、私は本当に必要なものです。
追加された 著者 Nathan Cantos,
それはテーブルなので、私はインデックスを持っているとは思わない。
追加された 著者 Nathan Cantos,

4 答え

これをサブクエリの代わりにJOINに変換するアイデアがあります。このテクニックは実際に とそのユーザーからの回答(それは根本的に効率的です)に参加し、最終結果(HAVING内)から除外します。これをさらに改善することは可能です(私はテストしませんでしたが、IS NULLチェック可能性があります代わりにWHERE句に移動する可能性があります)。

これで、あなたはどこになりたいのですか?

SELECT question.quserid, COUNT(question.quserid) as num_questions
FROM qanda as question 
LEFT OUTER JOIN qanda as answers 
  ON question.qid = answers.qid AND answers.auserid = 'myusername'
GROUP BY question.quserid
ORDER BY num_questions DESC
HAVING answers.auserid IS NULL;

編集:もう少し説明します。これが終わり、他の誰かがアイデアを解決するのに役立ちます。

基本的に、クエリーの主要部分はすべての質問を正確に1回(LEFT OUTER)選択し、関心のあるユーザーが回答した質問については、JOINされた列も選択します。これにより、候補の結果セットにすべての質問があり、関心がない(つまり、結合されていない列)にフラグが付加された状態になります。次に、NULLでないjoin'dデータを持つ行をグループ化して拒否します。

2
追加された
クエリに2つの; があります。 HAVING が実行されますか?
追加された 著者 Fahim Parkar,
こちらを参照してください。あなたとOPの答えは一致しません。
追加された 著者 Fahim Parkar,
1つの質問には多くの回答があるので、1つのテーブルには多くのqidがあります。つまり、qidはこのテーブルの主キーではありません。 こちらをご覧ください。
追加された 著者 Fahim Parkar,
私はこの解決策を考えたときに私がそれを認識していたと思う。それはqidに関連して動作しない理由はありますか?
追加された 著者 Chris Trahey,
実際、これが私のソリューション全体の基礎となります
追加された 著者 Chris Trahey,

With reference to @ctrahey answer I have changed query and got solution working as @ctrahey was not giving output as yours as shown here.

もしこれがより速いのであれば試してみてください。

SELECT question.quserid, COUNT(question.quserid) as num_questions
FROM qanda as question 
LEFT OUTER JOIN qanda as answers 
  ON question.qid = answers.qid AND answers.auserid = 'user2'
WHERE answers.auserid IS NULL
GROUP BY question.quserid
ORDER BY num_questions DESC;

sqlfiddle も参照してください。あなたの質問と上記の質問は同じ出力を与えています。

これがあなたの望むものであることを願っています。

0
追加された
これはどういう意味ですか?構文/タイプミス? SOが編集の回答を許可するのはなぜですか?私は私の答えでどこにいても動いていると言いました...
追加された 著者 Chris Trahey,

これも試してみてください:

SELECT quserid, COUNT(*) AS num
FROM qanda
WHERE qid NOT IN 
        ( SELECT qid
          FROM qanda 
          WHERE auserid = 'user2' 
        )  
GROUP BY quserid 
ORDER BY num DESC 
LIMIT 0,1000 ;

これらのバリアントのインデックスを効率的に追加する必要があります。

(qid、quserid、auserid) PRIMARY キーですか?それは UNIQUE ですか(これは2つのうちの1つでなければなりません)。

(quserid、qid)のインデックスも役立ちます(テーブルがInnoDBエンジンを使用している場合)。

0
追加された

出力に基づいて、完全なテーブルスキャンが行われている場合にインデックス作成を実装できる候補を見つけようとします。

0
追加された