如何使用外键从SQLite表中提高DELETE性能?

时间:2019-02-13 23:21:17

标签: python sqlite

在启用了外键的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

1 个答案:

答案 0 :(得分:0)

来自the docs

  

应用程序每次从父表中删除行时,都会执行以下SELECT语句的等效操作来搜索子表中的引用行:

SELECT rowid FROM <child-table> WHERE <child-key> = :parent_key_value
     

如果此SELECT完全返回任何行,则SQLite得出结论,从父表中删除该行将违反外键约束并返回错误。如果修改了父键的内容或在父表中插入了新行,则可能会运行类似的查询。

在启用FK的情况下,每次删除都会做额外的工作。我认为您在保留外键约束的同时无法避免这种情况。