10

私はNewsStoriesテーブルを持っていますが、それは私がいくつかの関連テーブルと結合したままです。各ニュース記事には、複数の画像、カテゴリ、およびアドレスを含めることができます。そのため、クエリは基本的に次のようになります。

SELECT * FROM NewStories 

LEFT JOIN Images ON Newstories.id=Images.story_id

LEFT JOIN Categories ON NewsStories.id=Categories.story_id

LEFT JOIN Addresses ON NewsStories.id=Addresses.story_id

WHERE ...

通常、ストーリーごとにいくつかの画像と住所、および1つまたは2つのカテゴリがあります。 NewsStoriesテーブルには約10,000の記事があります。

問題は、パフォーマンスがかなり遅いことです(15〜20秒程度ですが、かなり変動しますが、5秒程度にまで低下することもあります)。

それをスピードアップするためにクエリを体系化するより良い方法があるかどうか私は不思議に思っていました(私はSQLについてはかなり新しいです)。

特に、あるストーリーの行数に、画像数×アドレス数×カテゴリ数を掛けたのは、非常に無駄が多いようです。

私は本質的に、ニュースストーリーの特性をフロントエンドで操作できる単一のオブジェクトに再構築しようとしています。

これが説明です(フォーマットが正しく出てこない場合は謝罪)。 「Using where」であれば、アドレスを正しく索引付けしていないと思います。あれは正しいですか?

id  select_type table   type    possible_keys   key key_len ref rows    Extra

1   SIMPLE  Addresses   ALL NULL    NULL    NULL    NULL    6640    Using where

1   SIMPLE  NewsStories eq_ref  PRIMARY PRIMARY 767 NewsStories.Addresses.story_id 1    Using where

1   SIMPLE  Images  ref PRIMARY PRIMARY 767 NewsStories.NewsStories.id  1   Using index

1   SIMPLE  Categories  ref PRIMARY PRIMARY 767 NewsStories.NewStories.id   1


  • id select_typeテーブル・タイプpossible_keysキーkey_len ref行追加1単純アドレスALL NULL NULL NULL NULL 6640 where 1の使用SIMPLE NewsStories eq_ref PRIMARY PRIMARY 767 NewsStories.Addresses.story_id 1 where 1の使用SIMPLEイメージref PRIMARY PRIMARY 767 NewsStories.NewsStories.id 1を使用します。 index 1シンプルカテゴリref PRIMARY PRIMARY 767 NewsStories.NewStories.id 1 - Vijay Boyapati
  • この質問に対する私の答えを見てください。stackoverflow.com/questions/6771975/sql-joining-6-tables/… - yper-crazyhat-cubeᵀᴹ

2 답변


6

  • WHEREステートメントとON条件にあるフィールドに索引があることを確認してください。主キーはデフォルトで索引付けされていますが、必要に応じて手動で索引を作成することもできます。

CREATE [UNIQUE | FULLTEXT | SPATIAL]インデックスindex_name       [index_type]       ON tbl_name(index_col_name、...)       [index_type]

index_col_name:       col_name [(length)] [ASC | DESC]

index_type:       使用中{BTREE |ハッシュ}

  • すべてのテーブルのすべての列を本当に選択する必要があるかどうかを確認しますか?そうでない場合は、必要な列だけを選択するようにしてください。使用しないでください。選択*

  • 本当にLEFT JOINSが必要かどうかを再確認し、必要でなければINNER JOINを使用してください。

  • クエリを調整した後もパフォーマンスが依然として問題になる場合は、結合を排除するためにスキーマを非正規化することを検討してください。

  • sphinxsearchやmemcachedなどのキャッシュアプリケーションを使用してデータベースの負荷を減らすことを検討することもできます。

  • 実際のテーブルではなく、ビューへの結合がないことを確認します。

参照先

http://www.sphinxsearch.com

http://dev.mysql.com/doc/refman/5.0/en/create-index.html


  • ありがとうマーク。フォローアップの質問:左側の結合のONに表示される列にインデックスを付ける必要がある理由はわかりましたが、どこで列にインデックスを付ける必要があるのか理解できません。これらのコラムは私がフィルタにかけたいと思うかもしれないニュース記事のさまざまな属性ですが、私は索引付けにそれほど価値があるとは思わない。結合で使用されていないインデックス列を使用すると、パフォーマンスが本当に向上しますか?もしそうならなぜですか? - Vijay Boyapati
  • はい、これはmysqlリファレンスガイドに明示的に記載されています。 「MySQLはこれらの操作にインデックスを使用します。WHERE句に一致する行をすばやく見つけるために。」dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html - Mark Basmayor
  • 優秀な。ポインタをありがとう。 - Vijay Boyapati
  • の賢い答えCheck none of your joins are to views rather than actual tables。 (そして) - NullPointer

0

テーブルに適切なインデックスが付けられていることを確認してください。データを選択するために使用するすべての列にインデックスを付ける必要があります。そうしないと、MySQLはテーブル内のすべての行を通過します。

クエリを説明してみてください(EXPLAIN SELECT * FROM ...etcMySQLコンソールで、MySQLがテーブルを内部でどのように処理するかを確認します。さらに助けを求めるためにあなたの質問に結果を貼り付けてください。


  • id select_typeテーブル型possible_keysキーkey_len ref行エクストラ1 SIMPLEアドレスALL NULL NULL NULL NULL 6640 where 1を使う単純なeq_ref PRIMARY PRIMARY 767 NewsStories.Addresses.story_id 1どこで1 SIMPLEの画像を使うPRIMARY PRIMARY 767 NewsStories .NewsStories.id 1インデックス1を使うSIMPLEカテゴリーref PRIMARY PRIMARY 767 NewsStories.NewStories.id 1 - Vijay Boyapati

リンクされた質問


関連する質問

最近の質問