これが私がしたことであり、合計実行時間を10分の1に短縮しました。
元のクエリの実行プランから気付いたのは、すべての結果を並べ替えるためにfilesortを使用し、インデックスを無視していたことです。それは少し無駄です。
私のテストデータベース:5 Mレコード、20GBサイズ。質問と同じテーブル構造
最初のクエリでblobColを直接取得する代わりに、最初にすべてのページの先頭にある「name」の値を取得します。結果が0になるまで、このクエリを無期限に実行します。毎回、結果をリストに追加します
SELECT name
FROM my_table
where id = <anyId> // I use the id column for partitioning so I need this here
order by name
limit <pageSize * pageNumber>, 1
正弦ページ番号は以前は不明でした。値0から開始し、クエリがnullを返すまで増分を続けます。 select count(*)を実行することもできますが、それ自体に時間がかかる可能性があり、最適化には役立ちません。ページ数が約60を超えると、各クエリの実行に約2秒かかりました。
私の場合、ページサイズは5000だったので、位置0、5001、10001、15001などの「名前」文字列のリストを取得しました。ページ数は1000であることが判明し、1000の結果のリストをメモリに保存することは高価ではありません。
次に、リストを繰り返し処理して、このクエリを実行します
SELECT blobCol
FROM my_table
where name >= <pageHeader>
and name < <nextPageHeader>
and city="<any string>"
and id= 1
これはN回実行されます。ここで、N=以前に取得したリストのサイズです。 'name'が主キー列であり、'city'にもインデックスが付けられているため、EXPLAINは、この計算がインデックスを使用してメモリ内で実行されることを示しています。
現在、各クエリの実行には、元の30〜40ではなく、1秒かかります。したがって、1ページあたり2秒の前処理時間を組み合わせると、1ページあたりの合計時間は30〜40秒ではなく3〜4秒になります。
誰かがより良い解決策を持っている場合、またはこれに明らかに問題がある場合は、私に知らせてください