1

UNIONALLによって2つのテーブルから作成されたクエリがあります。結果は、(Webアプリケーションの一般的なリストのように)順序付けてページ付けする必要があります。

元のクエリ(簡略化)は次のとおりです。

SELECT name, id
FROM _test1 -- conditions WHERE
UNION ALL
SELECT name, id
FROM _test2 -- conditions WHERE
ORDER BY name DESC LIMIT 10,20

問題は、2つのテーブルにそれぞれ100万行を超える行があり、クエリが非常に遅いことです。

UNION ALLから最適化されたページ付けリストを取得するにはどうすればよいですか?

ポストデータ:

Stack Overflowの検索を使用しましたが、これに似た質問がいくつか見つかりましたが、答えが正しくないか、質問がまったく同じではありません。2つの例:

UNIONmysqlクエリを最適化する

MySQLクエリでのUNION操作とLIMIT操作の組み合わせ

Stack Overflowでは、誰もこの質問に答えられなかったことに驚いています。たぶん、このクエリをより効率的に行うことは不可能ですか?この問題の解決策は何でしょうか?

4

1 に答える 1

4

少なくともパフォーマンスを向上させるために、2 番目のリンクのソリューションに似たものを使用できると思いますが、後のページで優れたパフォーマンスが得られるとは思えません。例えば:

(   SELECT name, id
    FROM _test1 -- conditions WHERE
    ORDER BY name DESC LIMIT 0, 30
)
UNION ALL
(   SELECT name, id
    FROM _test2 -- conditions WHERE
   ORDER BY name DESC LIMIT 0, 30
)
ORDER BY name DESC
LIMIT 10, 20

基本的に、各サブクエリを、特定のページにある可能性のある行のサブセットに制限しています。このようにして、返す 10 行を決定する前に、各テーブルから 20 行を取得してマージするだけで済みます。そうしないと、サーバーが各テーブルからすべての行を取得し、それらを並べ替えてマージし、正しい行を見つけようとする可能性があります。

ただし、MySQL はあまり使用しないため、エンジンが想定どおりに動作することを保証することはできません :)

いずれにせよ、後のページに到達すると、ますます大きなデータセットをマージすることになります。ただし、UI では、ユーザーが (たとえば) 5000 ページに移動できる一連のレコードを取得できるようにするべきではないと私は強く考えています。さらにフィルタリングする必要があります。最初の 100 ページ (またはその他の数) を表示させることもできますが、それ以外の場合は、結果をより適切に制限する必要があります。あくまで私の意見ですが。

于 2011-09-27T19:19:11.207 に答える