4

イベント結果のテーブルがあり、指定されたプレーヤーのリストについて、プレーヤーごとに最新の n イベントをフェッチする必要があります。

これは iOS 上にあるため、高速である必要があります。サブクエリまたは結合を使用するグループごとの上位 n ソリューションを多数見てきましたが、これらは macbook pro でも 100k 行のデータセットに対して実行が遅くなります。これまでのところ、最大 6 人のプレーヤーでのみこれを実行するため、私のばかげた解決策は、6 つの個別のクエリを実行することです。それほど遅くはありませんが、もっと良い方法があるはずですよね? 私が今やっていることの要点は次のとおりです。

results_by_pid = {} 
player_ids = [1,2,3,4,5,6]
n_results = 6
for pid in player_ids:
  results_by_pid[pid] = exec_sql("SELECT * 
                                  FROM results
                                  WHERE player_id = #{pid}
                                  ORDER BY event_date DESC
                                  LIMIT n_events")

そして、私は陽気な道を進みます。しかし、これを単一の高速クエリに変換するにはどうすればよいでしょうか?

4

2 に答える 2

1

これ以上の方法はありません。役立つかもしれないSQLウィンドウ関数はSQLiteに実装されていません。

SQLiteは、ほとんどのロジックがアプリケーションにとどまる組み込みデータベースとして設計されています。ネットワーク通信を回避する必要があるクライアント/サーバーデータベースとは対照的に、SQLコマンドとプログラムロジックを混在させることによるパフォーマンスの低下はありません。

あまり馬鹿げていない解決策では、SELECT player_id FROM somewhere事前にいくつかのことを行う必要がありますが、これは問題ありません。

個々のクエリを効率的にするには、2つの列player_idとに1つのインデックスがあることを確認してくださいevent_date

于 2013-03-15T08:28:19.573 に答える
1

これはあまり答えにはなりませんが、ここに行きます...

物事を本当に迅速に行うには、データとスキーマ自体の性質からのアイデアが必要になる場合があることがわかりました。たとえば、順序付きリストの検索は、順序なしリストの検索よりも高速ですが、設計と実行の両方でコストを事前に支払う必要があります。

したがって、SQLite が検索する必要があるレコードの数を減らす可能性のあるデータに自然なパーティションがあるかどうかを自問してください。最新の n 件のイベントが特定の期間内にあるかどうかを尋ねる場合があります。それらはすべて過去 7 日間のものでしょうか? 先月?その場合は、より複雑な検索を実行する前に、データのチャンク全体を除外するクエリを作成できます。

また、すぐに動作させることができない場合は、UX の策略を検討することもできます。すっごく多くのエンジニアが、自分の UX を巧みに使いこなせていません。ビュー コントローラーのプッシュの結果として、クエリが実行されますか? 次に、PREVIOUS ビュー コントローラーからバックグラウンド スレッドに移行するように設定し、iOS のアニメーション中に動作させます。プッシュ アニメーションにはどのくらいの時間がかかりますか? 2秒?ユーザーはどの時点で (何らかの UX コントロールを介して)playeridsクエリを実行することをアプリに指示しますか? 彼がそのボタンまたは TVCell に触れるとすぐに、データをプリフェッチできます。したがって、やらなければならない作業の合計がO(n log n)である場合、それはおそらくO(n)O(log n)の部分に分割できることを意味します。

私が自分のハードワークを避ける間、ちょっと考えてみてください。


より多くの考え

前の n 回の挿入の ID を含む別のテーブルはどうですか? テーブルのサイズが n を超えた場合に、古い ID を削除するトリガーを追加できます。言う..

CREATE TABLE IF NOT EXISTS recent_results
   (result_id INTEGER PRIMARY KEY, event_date DATE);
// is DATE a type? I don't know. you get the point

CREATE TRIGGER IF NOT EXISTS optimizer
   AFTER INSERT ON recent_results
   WHEN (SELECT COUNT(*) FROM recent_results) > N
   BEGIN
      DELETE FROM recent_results
      WHERE result_id = (SELECT result_id
                         FROM recent_results
                         WHERE event_date = MIN(event_date));
// or something like that. I have no idea if this will work,
// I just threw it together.

または、アプリのロード時にデータを入力し、アプリの実行中にトランザクションを実行するときに最新の状態に保つ、一時的なメモリ ベースのテーブルを作成することもできます。そうすれば、高額な料金を一度だけ支払うことができます。

もう少し考えてみてください。創造力を働かせてください。通常は、データ構造とアルゴリズムとして必要なものを定義できることを覚えておいてください。幸運を!

于 2013-03-14T16:52:10.470 に答える