performance - SQLite 闭包表实现的性能问题
问题描述
我首先要说我对 SQL 和数据库系统相当陌生,所以请原谅我可能会犯的任何新手错误。
我正在使用闭包表在 SQLite 数据库中插入分层数据。我正在为 SQLite 版本 3.26.0 使用 C# (.NET 4.6.1) 和 SQLite 预编译的 32 位 DLL (x86)。插入的分层数据包含约 240000 个元素,最大树深度不大于 7。
我的分层元素表是:
CREATE TABLE element (elementId INTEGER PRIMARY KEY, parentId INTEGER, elementName TEXT, FOREIGN KEY (parentId) REFERENCES element(elementId));
我的闭包表定义为:
CREATE TABLE hierarchy (parentId INTEGER, childId INTEGER, depth INTEGER, FOREIGN KEY(parentId) REFERENCES element(elementId), FOREIGN KEY(childId) REFERENCES element(elementId));
元素使用经典堆栈插入,该堆栈从“根”元素开始,在事务处理期间将元素的成员添加到其中,使用:
INSERT INTO element VALUES (<ELEMENT_ID>, <PARENT_ID>'<ELEMENT_NAME');
我用“自我”关系初始化闭包表,使用:
INSERT INTO hierarchy(parentId, childId, depth) VALUES (<ELEMENT_ID>, <ELEMENT_ID>, 0);
这些插入不会导致任何问题,只需几秒钟即可执行。
接下来,我使用相同的堆栈方法再次遍历所有元素以构建闭包表(注意:我可能会在前面的指令的同时执行此操作,但是我在单独的循环中执行此操作以隔离性能问题)使用以下代码(在另一个事务中):
INSERT INTO hierarchy SELECT p.parentId, c.childId, p.depth+c.depth+1 FROM hierarchy p, hierarchy c WHERE p.childId=<PARENT_ID> AND c.parentId=<ELEMENT_ID>;
但是,此查询需要数小时甚至数天才能执行。它的执行时间也越来越长。我知道它在闭包表中插入了很多元素(当前元素与其所有祖先之间的每个关系一个条目),但我想知道是否可以采取任何措施来提高这里的性能?
谢谢
解决方案
您需要子键和父键的索引。还将所有内容包装在事务中。
更好的是,使用单个递归 CTE 生成闭包表,例如
with recursive
closure as (
select elementId, elementId as parentId, 0 as depth from element
union all
select closure.elementId, element.parentId, 1 + depth as depth
from closure, element where closure.parentId = element.elementId
)
select * from closure
要实际创建表,请使用类似create table hierarchy as
将上述结果放入表中的方法。
推荐阅读
- javascript - 身份验证后重定向到 Passport.js 中的上一页(不重复)Node.js
- reactjs - 在单个 setState 调用上多次响应状态更新
- pascal - 无法编译 - Turbo Pascal
- mysql - 在 Ubuntu 20.04 上从 MySQL 迁移到 MariaDB
- javascript - d3.js 轴添加刻度值
- git - 写入 node_modules 目录时的管道权限问题
- c++ - 编译错误:Boost.Range / MPL 中没有名为“type”的类型
- java - 构造转换器失败:错误:无法解析 C:
- java - 将类的实例转换为服务(android/Java)时的问题
- ffmpeg - windows上的ffmpeg网络摄像头流到sdl