1

クエリを生成しました

select 
    mailsource2_.file as col_0_0_, 
    messagedet0_.messageId as col_1_0_, 
    messageent1_.mboxOffset as col_2_0_, 
    messageent1_.mboxOffsetEnd as col_3_0_, 
    messagedet0_.id as col_4_0_ 
from MessageDetails messagedet0_, MessageEntry messageent1_, MailSourceFile mailsource2_ 
where messagedet0_.id=messageent1_.messageDetails_id 
and messageent1_.mailSourceFile_id=mailsource2_.id 
order by mailsource2_.file, messageent1_.mboxOffset;

Explain によると、フル スキャンはなく、インデックスが使用されます。

+----+-------------+--------------+--------+------------------------------------------------------+---------+---------+--------------------------------------+------+----------------------------------------------+
| id | select_type | table        | type   | possible_keys                                        |key     | key_len | ref                                  | rows | Extra           |
+----+-------------+--------------+--------+------------------------------------------------------+---------+---------+--------------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | mailsource2_ | index  | PRIMARY                                              |file    | 384     | NULL                                 | 1445 | Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | messageent1_ | ref    | msf_idx,md_idx,FKBBB258CB60B94D38,FKBBB258CBF7C835B8 |msf_idx | 9       | skryb.mailsource2_.id                | 2721 | Using where           |
|  1 | SIMPLE      | messagedet0_ | eq_ref | PRIMARY                                              |PRIMARY | 8       | skryb.messageent1_.messageDetails_id |    1 |           |
+----+-------------+--------------+--------+------------------------------------------------------+---------+---------+--------------------------------------+------+----------------------------------------------+


CREATE TABLE `mailsourcefile` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `file` varchar(127) COLLATE utf8_bin DEFAULT NULL,
  `size` bigint(20) DEFAULT NULL,
  `archive_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `file` (`file`),
  KEY `File_idx` (`file`),
  KEY `Archive_idx` (`archive_id`),
  KEY `FK7C3F816ECDB9F63C` (`archive_id`),
  CONSTRAINT `FK7C3F816ECDB9F63C` FOREIGN KEY (`archive_id`) REFERENCES `archive` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1370 DEFAULT CHARSET=utf8 COLLATE=utf8_bin

また、ファイルと mboxOffset のインデックスもあります。SHOW FULL PROCESSLIST は、mysql が結果をソートしており、数分以上かかることを示しています。結果セットのサイズは 5M レコードです。これを最適化するにはどうすればよいですか?

4

4 に答える 4

3

クエリ自体に多くの最適化が必要だとは思わないでください。結合すると読みやすくなりますが、最近の iirc mysql はこの種の構造を完全に検出し、結合自体を計画することができます。

おそらく役立つのは、tmp_table_size と max_heap_table_size の両方を増やして、このクエリの結果セットをディスクに書き込むのではなく、メモリに保持できるようにすることです。

インメモリ一時テーブルの最大サイズは、tmp_table_size 値と max_heap_table_size 値の最小値です。

http://dev.mysql.com/doc/refman/5.5/en/internal-temporary-tables.html

説明の「一時的な使用」は、一時テーブルを使用していることを示しています (上記のリンクをもう一度参照してください)。これは、大量のデータのためにディスクに書き込まれる可能性があります (詳細については、上記のリンクを参照してください)。 . ファイル列だけでも 1 から 384 バイトの間のどこかにあるので、推定のために半分を取り、残りの列を無視すると、結果セットの行ごとに 192 バイトになります。

1445 * 2721  =   3,931,845 rows
     * 192   = 754,914,240 bytes
     / 1024 ~=     737,221 kb
     / 1024 ~=         710 mb

これは確かに max_heap_table_size (16,777,216 バイト) より大きく、おそらく tmp_table_size より大きくなっています。

そのような結果をディスクに書き込む必要がないことは、間違いなく速度を向上させます。

幸運を!

于 2013-01-11T09:00:08.243 に答える
1

@raheel shan が上で言ったように、いくつかJOINの s を試してみてください:

select 
    mailsource2_.file as col_0_0_, 
    messagedet0_.messageId as col_1_0_, 
    messageent1_.mboxOffset as col_2_0_, 
    messageent1_.mboxOffsetEnd as col_3_0_, 
    messagedet0_.id as col_4_0_ 
from 
  MessageDetails messagedet0_ 
inner join 
  MessageEntry messageent1_ 
on 
  messagedet0_.id = messageent1_.messageDetails_id 
inner join 
  MailSourceFile mailsource2_ 
on 
  messageent1_.mailSourceFile_id = mailsource2_.id
order by 
  mailsource2_.file, 
  messageent1_.mboxOffset

キーが外れていたら申し訳ありませんが、要点は伝わったと思います。

于 2013-01-04T21:30:35.197 に答える
0

次のような結合でクエリを記述します

選択する

col_0_0_ として mailsource2_.file、col_1_0_ として messagedet0_.messageId、col_2_0_ として messageent1_.mboxOffset、col_3_0_ として messageent1_.mboxOffsetEnd、col_4_0_ として messagedet0_.id

MessageDetails m0から

内部結合 MessageEntry m1 on m0.id = m1.messageDetails_id

内部結合 MailSourceFile m2 on m1.mailSourceFile_id = m2.id

m2_.file、m1_.mboxOffsetによる順序;

あなたの説明を見て、私の意見では良くないことが3つ見つかりました

余分な列で 1 つのファイルの並べ替え

タイプ列の 2 つのインデックス

384 である 3 つのキーの長さ

キーの長さを短くすると、使用する文字セットと部分インデックスを考慮して、すばやく取得できる場合があります

ここで、順序付けにインデックスを強制し、結合にインデックスを使用することができます (適切な複数列インデックスを作成して割り当てます) 同じテーブルに存在する列で順序付けすることは常に良いことを覚えておいてください

インデックス タイプは、インデックス列全体をスキャンしていることを表しますが、これは適切ではありません

于 2013-01-12T10:25:56.207 に答える