0

私は3つのテーブルを持っています。postadata以下のクエリを使用して、すべての投稿とそのタグを連結して取得するクエリを実行していますtagtag_data

    SELECT 
        postdata.data_id as data_id, 
        GROUP_CONCAT(DISTINCT(tag.tag_id)) as tag_ids, 
        GROUP_CONCAT(DISTINCT(tag.tag) ORDER BY tag.tag ASC) as tags
    FROM postdata
    LEFT JOIN tag_data as tag_data
            INNER JOIN tag as tag
                ON tag_data.tag_id = tag.tag_id
    ON postdata.data_id = tag_Data.data_id
    GROUP BY postdata.data_id
    LIMIT 1000

しかし、それは非常に遅いです。(約20秒)。以下は説明です、私は問題を見つけることができないようです

1   SIMPLE  postdata    index   NULL    source_id   4   NULL            158808  Using index; Using temporary; Using filesort
1   SIMPLE  tag_data    index   PRIMARY PRIMARY     8   NULL            45279   Using index
1   SIMPLE  tag         eq_ref  PRIMARY PRIMARY     4   tag_data.tag_id 1   

以下は投稿データのインデックスです

postdata    0   PRIMARY     1   data_id     A   120405  NULL    NULL        BTREE       
postdata    1   source_id   1   source_id   A   168     NULL    NULL        BTREE   

クエリに問題がありますか?より効率的に書く方法はありますか?それとも、欠落しているインデックスですか?

更新: jordeu のコメントに従ってインデックス情報を追加する

SHOW TABLE STATUS FROM [database_name] WHERE Name='postdata'

Name        Engine  Version Row_format  Rows    Avg_row_length  Data_length Max_data_length Index_length    Data_free   Auto_increment  Create_time Update_time Check_time  Collation   Checksum    Create_options  Comment
postdata    InnoDB  10      Compact     158645  43              6832128     0               8421376         4194304     NULL            2012-03-08 09:22:40 NULL    NULL    utf8_unicode_ci NULL

「key_buffer_size」のような変数を表示

key_buffer_size 16777216
4

4 に答える 4

1

LEFT JOIN の後に INNER JOIN を使用する必要はありません。

このアプローチを試してください:

SELECT 
    postdata.data_id as data_id, 
    GROUP_CONCAT(DISTINCT(tag.tag_id)) as tag_ids, 
    GROUP_CONCAT(DISTINCT(tag.tag) ORDER BY tag.tag ASC) as tags
FROM postdata
    LEFT JOIN tag_data as tag_data
      ON postdata.data_id = tag_Data.data_id
    LEFT JOIN tag as tag
      ON tag_data.tag_id = tag.tag_id
GROUP BY postdata.data_id
LIMIT 1000
于 2012-04-13T13:08:37.937 に答える
1

問題は、インデックスがメモリに収まらないことである可能性があります。これにより、MySQL が遅くなります。

たとえば、「key_buffer_size」を 160Mb に増やします。

SET GLOBAL key_buffer_size = 167772160

InnoDB を使用している場合は、「innodb_buffer_size」も増やす必要がある場合があります。

于 2012-04-13T13:43:10.010 に答える
0

コメントされているように、DISTINCTが悪である場合は、を削除して、次のDISTINCTように一意にすることができます。

$arr_tag_ids = array_unique(implode(',', $row->tag_ids));
$arr_tags = array_unique(implode(',', $row->tags));
于 2012-04-13T12:59:46.443 に答える
0

EXPLAIN から、最初の参加で INDEX を使用していないようです。これは、両方の JOIN と両方の ON 条件があるためである可能性があります。そのようにフォーマットされたJOINを見たことがありません。このように変更してみてください

SELECT 
    postdata.data_id as data_id, 
    GROUP_CONCAT(DISTINCT(tag.tag_id)) as tag_ids, 
    GROUP_CONCAT(DISTINCT(tag.tag) ORDER BY tag.tag ASC) as tags
FROM postdata
    LEFT JOIN tag_data as tag_data
      ON postdata.data_id = tag_Data.data_id
    LEFT JOIN tag as tag
      ON tag_data.tag_id = tag.tag_id
GROUP BY postdata.data_id
LIMIT 1000

次に、EXPLAIN を再実行して、違いが生じるかどうかを確認します。また、最初の JOIN には必ず LEFT JOIN が必要ですか? 可能であれば、それを INNER JOIN に変更すると役立つ場合があります。

于 2012-04-13T13:04:54.910 に答える