Tho*_*que 5 sql optimization performance hierarchy hierarchical-data
我有一个数据库表,表示文件和目录的层次结构,具有以下结构(简化):
ItemId int Path text Type int (0 for files, 1 for directories) ParentId int BackupTime datetime
目前该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
Run Code Online (Sandbox Code Playgroud)
我的问题是我似乎找不到有效的方法.上面的查询对大量数据需要太长时间(此表通常包含超过100K行)
min(BackupTime)只搜索直接孩子可能会更快:
update Items i
set BackupTime = (select min(BackupTime)
from Items d
where d.ParentId = i.ItemId)
where i.Type = 1
Run Code Online (Sandbox Code Playgroud)
但为了实现这一点,我必须确保后代将在他们的祖先之前更新,所以我必须从下往上递归地遍历层次结构.问题是我没有简单的方法知道哪些项目是层次结构中最深的.我正在使用SQLite,所以我不能使用分层查询.
有关如何有效地做到这一点的任何想法?
理想情况下,我希望能够在单个UPDATE查询中执行此操作,但如果不可能,我会对其他选项开放,只要它们有效
这是在黑暗中进行的尝试,但它可能会起作用。这是手动处理自下而上问题的尝试。(我不知道 sqlite 的限制,但这可能是标准 SQL-92,希望没问题。)
第 1 步:决定如何处理空目录。我认为这里的解决方案仅在没有空目录或空目录最初更新时才有效,因此它们具有人为的非空备份时间。(人工的 BackupTime 应该是什么可能很重要,具体取决于数据发生更改时如何维护 BackupDate 列。使用当前日期或人工的未来日期可能有效,但您应该考虑一下。)
步骤 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
)
Run Code Online (Sandbox Code Playgroud)
换句话说,当您需要并且还拥有所有信息时更新目录的 BackupTime:当它们的 BackupTime 为 null 并且它们不包含 BackupTime 值也为 null 的子目录时。
因此,第一次运行此命令时,它将为所有不包含子目录、仅包含文件的目录设置 BackupTime。第二次,它将为包含子目录但不包含子子目录的目录设置BackupTime。
您也许可以通过将 BackupTime 设置为 coalesce((select...),current_timestamp) 来处理空目录问题。
| 归档时间: |
|
| 查看次数: |
423 次 |
| 最近记录: |