5

次の構造(簡略化)のファイルとディレクトリの階層を表すデータベーステーブルがあります。

アイテム ID int
パス テキスト
タイプ int (ファイルの場合は 0、ディレクトリの場合は 1)
親 ID int
BackupTime 日時

現在、このBackupTime列はファイルにのみ使用され、ディレクトリの場合は null に設定されています。

ここで、ディレクトリについてもこの列に入力する必要があります。これはBackupTime、すべての子孫 (ファイルとディレクトリ) の最小値でなければなりません。

この (素朴で非効率的な) クエリは、私がやりたいことを示しています。

update Items i
set BackupTime = (select min(BackupTime)
                  from Items d
                  where d.Path like i.Path || '%'
                  and d.Type = 0)
where i.Type = 1

私の問題は、効率的なアプローチが見つからないように見えることです。上記のクエリは、大量のデータに対して非常に時間がかかります (このテーブルには、多くの場合、10 万行を超える行が含まれます)。

min(BackupTime)直接の子のみを検索する方がおそらく高速です。

update Items i
set BackupTime = (select min(BackupTime)
                  from Items d
                  where d.ParentId = i.ItemId)
where i.Type = 1

しかし、これが機能するためには、先祖よりも先に子孫が更新されるようにする必要があるため、階層をボトムアップで再帰的にたどる必要があります。問題は、どの項目が階層の中で最も深いかを簡単に知る方法がないことです。SQLite を使用しているため、階層クエリを使用できません。

これを効率的に行う方法について何か考えはありますか?

理想的には、単一の UPDATE クエリで実行できるようにしたいのですが、それが不可能な場合は、効率的である限り、他のオプションを受け入れることができます。

4

1 に答える 1

1

これは暗闇でのショットですが、うまくいくかもしれません。ボトムアップの問題を手動で処理する試みです。(sqlite の制限はわかりませんが、これはおそらく標準の SQL-92 であり、うまくいけば問題ありません。)

ステップ 1: 空のディレクトリをどのように処理するかを決定します。ここでの解決策は、空のディレクトリがない場合、または空のディレクトリが最初に更新されて人工的な非 NULL BackupTime を持つ場合にのみ機能すると思います。(データに変更があった場合に BackupDate 列をどのように維持するかによって、人為的な BackupTime が重要になる場合があります。現在の日付または人為的な将来の日付を使用してもうまくいくかもしれませんが、それについて考える必要があります。)

ステップ 2. 影響を受ける行がなくなるまで、次のクエリを繰り返し実行します。

  update Items i set
    BackupTime = (
      select min(BackupTime)
      from Items d
      where d.ParentId = i.ItemId
    )
  where i.Type = 1
  and i.BackupTime is null
  and not exists (
    select *
    from Items d
    where d.ParentId = i.ItemId
    and d.Type = 1
    and d.BackupTime is null
  )

つまり、必要なときにディレクトリの BackupTime を更新し、すべての情報を取得します。BackupTime が null で、BackupTime 値も null のサブディレクトリが含まれていない場合です。

したがって、これを初めて実行すると、サブディレクトリを含まず、ファイルのみを含むすべてのディレクトリに対して BackupTime が設定されます。2 回目は、サブディレクトリを含むがサブサブディレクトリを含まないディレクトリの BackupTime を設定します。

BackupTimeをcoalesce((select...),current_timestamp)に設定することで、空のディレクトリの問題を処理できる場合があります。

于 2012-04-26T22:04:29.707 に答える