4

これをORDER BYで実行すると10 秒以上かかり、トラフィックが多いとサイトがクラッシュしてしまいます。

select *
from tbluserinfluences, tblcontent, tblusers
where tblcontent.userid = tblusers.id
and tbluserinfluences.userid = tblusers.id
and tbluserinfluences.lcase_influence = 'pink floyd'
order by tblcontent.score desc
limit 0, 160

ORDER BY を使用せずに同じクエリを実行すると、数ミリ秒しかかかりません。

select *
from tbluserinfluences, tblcontent, tblusers
where tblcontent.userid = tblusers.id
and tbluserinfluences.userid = tblusers.id
and tbluserinfluences.lcase_influence = 'pink floyd'
order by tblcontent.score desc
limit 0, 160

ここに説明があります

ここに画像の説明を入力

何か案は?私はそれを複数のクエリに分割したり、一時テーブルを作成したり、その他の助けになることを受け入れています。このクエリは、私 (および私のユーザー) を悩ませています。

ありがとう!

4

7 に答える 7

7

スコア列にインデックスが必要になる可能性があります。

于 2012-05-29T23:19:36.853 に答える
3

OK、まず最初に: LIMIT は、誰かが ORDER BY を追加するまで、多数の不適切なクエリを隠します。LIMIT は、指定された数のレコードが生成されるとすぐにクエリを救済するよう DB エンジンに招待します。 ORDER BY が追加されると、すべてのレコードが内部的に生成されますが、プログラマーには隠されます。LIMIT されたクエリが ORDER BY によって大幅に遅くなる場合、最初から良いクエリではありませんでした。

とは言っても、クエリ (および DB 設定) を改善するために行う小さな変更がたくさんあります。EXPLAIN プラン (これを含めることで上位 10% に入っています) を見ると、多くのことが際立っています。結果セットには 240,000 のレコードが並べ替えられています。「ファイルソートの使用」から、2パスソートステージが発生しているように見え、さらにクエリが一時テーブルを作成していますsort_buffer_size. per-session はグローバル バッファーではないため、100 の同時セッションがある場合は 256MB にしないでください。4MB または 8MB が適切な開始位置になると思います。

これで大幅に改善されない場合は、クエリ自体の作業を開始します。EXPLAIN の出力は、lcase_influenceインデックスに 300 バイト以上のキーがあることを示しています。これにインデックスを付けると、テーブルのサイズとinfluencename-indexの両方が削除されます。tblInfluence,tblInfluence.idtbluserinfluencestbluserinfluences

これで問題が解決しない場合は、出力レコード全体ではなく、必要最小限のフィールドのみをソートするようにソートを移動することを検討します。私もtblUsrContent直接参加しますtblUserInfluences-それは大きな違いはないと思いますが、それが私のコードである場合、可能であれば、結合の長いチェーンよりもシングルステップの結合を好みます。

于 2012-05-31T04:03:58.957 に答える
1

わかりました、これは大きなハックですが、問題の (一時的な) 解決策を見つけました。

クエリは、「ピンク フロイド」から「コールドプレイ」までの非常に人気のあるバンドを検索する場合にのみ遅くなります。それよりも人気のないバンドは、クエリが高速です。

試行錯誤の結果、クエリでtblcontent.scoreインデックスを使用するように強制すると、「ピンク フロイド」のような人気のあるバンドでは超高速ですが、「ロマンティックス」のようなあまり人気のないバンドでは遅くなることがわかりました。

ハッキーな解決策: 上位 100 バンドの強制スコア インデックス。MySql が他のすべてのバンドにデフォルトを使用できるようにします。はぁ。

したがって、ピンク フロイドクエリの高速バージョンは次のとおりです。

select *
from tbluserinfluences, tblcontent FORCE INDEX(score), tblusers
where tblcontent.userid = tblusers.id
and tbluserinfluences.userid = tblusers.id
and tbluserinfluences.lcase_influence = 'pink floyd'
order by tblcontent.score desc
limit 0, 160

そして、ロマンチックな(あまり人気のない) クエリの高速バージョンは次のとおりです。

select *
from tbluserinfluences, tblcontent, tblusers
where tblcontent.userid = tblusers.id
and tbluserinfluences.userid = tblusers.id
and tbluserinfluences.lcase_influence = 'pink floyd'
order by tblcontent.score desc
limit 0, 160

これは、私が Defcon 5 にいる間は、適切な解決策です。後でもっと洗練された方法を見つけます。

于 2012-05-29T23:54:52.187 に答える
0

これを試して

select 
ui.*,
tc.*
tu.*
from tbluserinfluences as ui
LEFT JOIN tblusers AS tu ON tu.id = ui.userid
LEFT JOIN tblcontent AS tc ON tc.userid = tu.id
where ui.lcase_influence = 'pink floyd'
order by ???.score desc
limit 0, 160

交換 ???関係するテーブルで。試すことはできませんが、それから始めましょう。

于 2012-05-29T23:28:53.840 に答える
0

スキーマが表示されない場合は、SCORE フィールドにインデックスを追加します。どのインデックスでも、INSERT のパフォーマンスに若干の影響がありますが、select クエリが最も重要な部分であるように思えます。

于 2012-05-29T23:24:11.247 に答える
0

これは私がそれを行う方法です

select * from (
 select *
 from tbluserinfluences, tblcontent FORCE INDEX(score), tblusers
 where tblcontent.userid = tblusers.id
 and tbluserinfluences.userid = tblusers.id
 and tbluserinfluences.lcase_influence = 'pink floyd'
 limit 0, 160) tbl
order by tbl.score desc

並べ替えてから制限するのではなく、最初に制限してから 160 レコードのみを並べ替えます

于 2013-07-16T07:25:07.453 に答える
0

ここでmy.iniファイルを変更します: innodb_buffer_pool_size = 300M - PC またはサーバーで使用可能なメモリに応じてサイズを変更します。私にとってはうまくいきました!

于 2013-04-22T13:51:17.693 に答える