3

この種の質問が以前に尋ねられたことは知っていますが、どれも私を解決に導きませんでした。

これが私のクエリです:

SELECT p.photoid, c.comment, p.path, p.smallfile, p.bigfile, c.userid, c.dateposted, u.username, c.likephoto 
  FROM bs_photocomments c, photos p, user u 
  WHERE c.active = 1 
    AND u.userid = c.userid 
    AND p.photoid = c.photoid 
    AND c.id = (SELECT ID FROM bs_photocomments WHERE photoid = p.photoid ORDER BY ID DESC LIMIT 1) 
  ORDER BY c.id DESC LIMIT 2

最後に少し説明AND

基本的に、20 枚のユニークな写真について最新のコメントを取得しようとしています。たとえば、1 枚の写真に 5 つのコメントがある場合、最後の 1 枚だけを表示します。

ORDER BY c.idキラーです。18 万のコメントと 10 万の写真しかありません。それを削除するとORDER BY、クエリはすぐに返されますが、明らかに必要な結果は得られません。

インデックスは次のとおりです。

+------------------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table            | Non_unique | Key_name           | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+------------------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| bs_photocomments |          0 | PRIMARY            |            1 | id          | A         |      183269 |     NULL | NULL   |      | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx1 |            1 | photoid     | A         |      183269 |     NULL | NULL   | YES  | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx2 |            1 | active      | A         |           4 |     NULL | NULL   | YES  | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx3 |            1 | dateposted  | A         |      183269 |     NULL | NULL   | YES  | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx4 |            1 | userid      | A         |        4953 |     NULL | NULL   | YES  | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx5 |            1 | puserid     | A         |        4072 |     NULL | NULL   | YES  | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx6 |            1 | id          | A         |      183269 |     NULL | NULL   |      | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx6 |            2 | photoid     | A         |      183269 |     NULL | NULL   | YES  | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx7 |            1 | photoid     | A         |      183269 |     NULL | NULL   | YES  | BTREE      |         |
| bs_photocomments |          1 | photocomments_idx7 |            2 | userid      | A         |      183269 |     NULL | NULL   | YES  | BTREE      |         |
+------------------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+


+--------+------------+--------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| Table  | Non_unique | Key_name     | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+--------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| photos |          0 | PRIMARY      |            1 | photoid      | A         |       57736 |     NULL | NULL   |      | BTREE      |         |
| photos |          1 | photos_idx1  |            1 | userid       | A         |        5773 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx2  |            1 | dateuploaded | A         |       57736 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx3  |            1 | camera       | A         |          17 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx4  |            1 | focallength  | A         |         308 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx5  |            1 | category     | A         |          96 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx6  |            1 | active       | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photo_idx7   |            1 | aperture     | A         |         354 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx8  |            1 | lenstype     | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx9  |            1 | film         | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |
| photos |          1 | photos_idx10 |            1 | originalfile | A         |       57736 |     NULL | NULL   | YES  | BTREE      |         |
+--------+------------+--------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+

何か案は?ありがとう!

4

1 に答える 1

4

このクエリは、(最大)20枚の異なる写真(bs_photocommentsテーブルのID値の昇順で識別される「recent-cy」を含む)の最も「最近の」コメントを1つ返します。返される20枚の写真は、最も「最近の」コメントが含まれている写真であり、最も「最近の」コメントから順に並べられます。(注:bs_photocomments内の行のみが考慮され、テーブル内にないかのように、active=1内の他のすべての行は無視されます。)bs_photocomments

SELECT p.photoid
     , c.comment
     , p.path
     , p.smallfile
     , p.bigfile
     , c.userid
     , c.dateposted
     , u.username
     , c.likephoto
  JOIN ( 
         SELECT n.photoid
              , MAX(n.id) AS max_id
           FROM bs_photocomments n
          WHERE n.active = 1 
          GROUP BY n.photoid
          ORDER BY max_id DESC
          LIMIT 20
       ) m
  JOIN bs_photocomments c
    ON c.id = m.max_id
  JOIN photos p
    ON p.photoid = c.photoid
  JOIN user u
    ON u.userid = c.userid
 ORDER BY c.id DESC
 LIMIT 20

「トリック」は、インラインビューを使用して、各フォトIDの「最新の」コメントを取得することです(インラインビューのエイリアスはとしてm)。それができたら、bs_photocommentsから行を取得し、ユーザーと写真から関連する行を取得するだけです。

元のクエリの実際のパフォーマンスの「キラー」は、結合述語の相関サブクエリであると思います。これは、bs_photocommentsテーブルのすべての行に対してクエリを実行したり、photosテーブルのすべての行に対してクエリを実行したりするという点で、かなりコストがかかります。


最適なパフォーマンスを得るには、個別の列ごとに(役に立たない)インデックスではなく、「カバーするインデックス」が必要になります。少なくとも、photoid先頭のインデックスとして.が後に続くbs_photocommentsのインデックスが必要idです。列を含めると、activeデータページにアクセスしなくても、「インデックスの使用」でインラインビュークエリを満たすことができます。

... ON bs_photocomments (photoid, id, active)

そのインデックスを使用すると、MySQLは各フォトIDの最大IDをかなり効率的に取得できるはずです。同様に、インデックスを持つ

... ON bs_photocomments (id, comment, userid, dateposted, likephoto)

これは、bs_photocommentsテーブル()に対する外部クエリcも「インデックスの使用」で満たすことができることを意味します。(MySQLは、ソート操作を必要とせずに、インデックスからのORDER BYを満たすことができる場合があります。(「Usingfilesort」がExtra列に表示されるかどうかを確認するには、EXPLAIN出力をチェックする必要があります。)

また、これらのカバーインデックスは、クエリのパフォーマンスをわずかに向上させる可能性があります。(基になるテーブルのページにアクセスせずにインデックスからクエリが満たされた場合、EXPLAIN出力には「インデックスの使用」と表示されます。)

  ON photos (photoid, path, smallfile, bigfile)

  ON user (userid, username)

個々の列にあるこれらの個別のインデックスのほとんどは役に立ちません。これらのインデックスのいずれかが使用される可能性は非常に低いため、リソースを消費するだけです。

于 2013-01-11T19:06:34.397 に答える