0

サーバー側のページネーションを使用した簡単なクエリがあります。問題は、WHERE句が高価な関数を呼び出し、関数の引数がユーザー入力であることです。ユーザーが探しているもの。

SELECT 
  * 
FROM 
  ( SELECT /*+ FIRST_ROWS(numberOfRows) */ 
      query.*, 
      ROWNUM rn FROM 
        (SELECT            
            myColumns 
          FROM 
            myTable 
            WHERE expensiveFunction(:userInput)=1  
          ORDER BY id ASC
        ) query
    )
WHERE rn >= :startIndex 
AND ROWNUM <= :numberOfRows

numberOfRows が小さいと仮定すると、これは機能し、迅速です。ただし、クエリの合計行数も知りたいです。ユーザー入力とデータベースのサイズによっては、クエリに数分かかる場合があります。私の現在のアプローチは、この値をキャッシュすることですが、それでもユーザーは最初の結果が表示されるまで数分待つ必要があります。

結果は Jquery datatables プラグインに表示され、serer 側のページングなどに非常に役立ちます。ただし、ページング コントロールを正しく表示するには、サーバーが合計レコードの値を返す必要があります。

最善のアプローチは何ですか?(注:PHP)

最初のページをすぐに偽の (より良いと推定される) 行数で返すと思いました。ページがロードされた後、クエリの合計行数を決定するメソッドへの ajax 呼び出しを実行し (その間にユーザーがページを表示するとどうなるでしょうか?)、偽造/推定された合計行数を更新します。

しかし、見積もりの​​仕方がわかりません。SAMPLE (0.1) で count(*) * 1000 を試してみましたが、何らかの理由で実際にはフルカウントクエリよりも時間がかかります。また、偽の/ランダムな値を返すだけでも少しハッキーに思えます。[次へ] ボタンを有効にするには、1 ページ サイズよりも大きくする必要があります。

他のアイデア?

4

2 に答える 2

1

それを行う1つの方法は、コメントで述べたように、「無数の」アプローチを使用することです。ボタンが常に有効になるようにクライアント側スクリプトを変更しNext、行がなくなるまで行をフェッチしてから、Nextボタンを無効にします。これ以上行がないことを知らせる通知メッセージをいつでも追加できるので、よりユーザーフレンドリーになります。

かなりの量のレコードが予想されることを考えると、ユーザーがすべての結果をページ分割するとは思えません。

もう 1 つの方法は、バックグラウンドでレコードのカウントを実行する cron ジョブをスケジュールし、結果としてtotals. ジョブの実行間隔は、挿入/削除の頻度に基づいて設定する必要があります。

次に、フロントエンドで、以前に に保存されたカウントを使用しますtotals。金額の妥当な概算を行う必要があります。

于 2012-09-26T11:57:12.080 に答える
0

DB エンジンによって異なります。mysql では、ソリューションは次のようになります。

    mysql> SELECT SQL_CALC_FOUND_ROWS * FROM tbl_name
        -> WHERE id > 100 LIMIT 10;
    mysql> SELECT FOUND_ROWS();

基本的に、SELECT (SQL_CALC_FOUND_ROWS) に別の属性を追加します。これは、クエリの実行中に、制限句が存在しないかのように行をカウントするように mysql に指示しますが、FOUND_ROWS は実際にその数を取得します。

Oracle については、次の記事を参照してください: How can I perform this query in oracle

他の DBMS にも似たようなものがあるかもしれませんが、私にはわかりません。

于 2012-09-26T11:40:46.747 に答える