在启用了外键的SQLite中从表中删除似乎很慢。有什么可以做的以提高性能(不禁用外键)?
import time
import sqlite3
def fk_check(state):
conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute("CREATE TABLE parent (id integer primary key, name)")
c.execute("CREATE TABLE child (id integer primary key, parent_id references parent)")
c.execute("CREATE INDEX parentindex ON child(parent_id);")
c.execute(f"pragma foreign_keys={state};")
for i in range(10000):
c.execute("insert into parent (name) values (?);", ('name'+str(i),))
for i in range(5000, 10000):
c.execute("insert into child (parent_id) values (?);", (i,))
start = time.time()
c.execute("delete from parent where id < 5000")
took = time.time()-start
print(f'fk-{state}: {took}')
fk_check('on')
fk_check('off')
fk_check('on')
fk_check('off')
具有以下输出:
fk-on: 0.8750052452087402
fk-off: 0.0007216930389404297
fk-on: 0.8769822120666504
fk-off: 0.0007178783416748047
答案 0 :(得分:0)
来自the docs:
应用程序每次从父表中删除行时,都会执行以下SELECT语句的等效操作来搜索子表中的引用行:
SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value
如果此SELECT完全返回任何行,则SQLite得出结论,从父表中删除该行将违反外键约束并返回错误。如果修改了父键的内容或在父表中插入了新行,则可能会运行类似的查询。
在启用FK的情况下,每次删除都会做额外的工作。我认为您在保留外键约束的同时无法避免这种情况。