ウィキペディアデータベースをローカルのMySQLデータベースにインポートし、ウィキページをフェッチするクエリを作成しました。
私の質問は次のとおりです:
SELECT
p.page_title,
p.page_id,
t.id,
text.old_text
FROM wikipedia_en.page p
INNER JOIN wikipedia_en.categorylinks cl
ON cl.cl_from = p.page_id AND cl.cl_type = 'page'
AND p.page_namespace = 0
AND p.page_is_redirect = 0
INNER JOIN wikipedia_en.revision ON revision.rev_id = p.page_latest
INNER JOIN wikipedia_en.text ON text.old_id = revision.rev_text_id
-- filter out pages with no topic
INNER JOIN topics.topics t ON cl.cl_to = t.topic
LIMIT 520000, 10000;
LIMIT
オフセットが0から始まる場合、クエリには約2秒かかりますが、オフセットが大きくなると(たとえば、520000)、クエリの実行にかなりの時間がかかります(たとえば、520000のオフセットの場合、約4分かかります)。
これがクエリExplainPlanです:
+----+-------------+----------+--------+------------------------------------------------+------------+---------+-----------------------------------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+--------+------------------------------------------------+------------+---------+-----------------------------------+--------+--------------------------+
| 1 | SIMPLE | t | ALL | topics_topic_index | NULL | NULL | NULL | 141413 | |
| 1 | SIMPLE | cl | ref | PRIMARY,cl_timestamp,cl_sortkey | cl_sortkey | 258 | topics.t.topic,const | 14 | Using where; Using index |
| 1 | SIMPLE | p | eq_ref | PRIMARY,name_title,page_redirect_namespace_len | PRIMARY | 4 | wikipedia_en.cl.cl_from | 1 | Using where |
| 1 | SIMPLE | revision | eq_ref | PRIMARY | PRIMARY | 4 | wikipedia_en.p.page_latest | 1 | |
| 1 | SIMPLE | text | eq_ref | PRIMARY | PRIMARY | 4 | wikipedia_en.revision.rev_text_id | 1 | |
+----+-------------+----------+--------+------------------------------------------------+------------+---------+-----------------------------------+--------+--------------------------+
サブクエリまたは一時テーブルを使用してこのクエリを最適化する方法があるかどうかを尋ねています。
OFFSET
は行を見つける必要がありますが、スキップします。 「中断したところを覚えておく」ことができれば、パフォーマンスが大幅に向上する可能性があります。
しかし、クエリにはさらに悪い問題があります。 ORDER BY
がないため、オプティマイザーは任意の順序で行を自由に提供でき、それによって行の欠落や重複が発生します。
ORDER BY
を追加した場合でも、テーブルが追加または削除されている場合、OFFSET
は行の欠落または重複を引き起こす可能性があります。
この問題について私の blog を読んでから、クエリを最初からやり直してください。