【发布时间】:2014-03-30 09:23:33
【问题描述】:
在我们的应用程序中,我们使用字母数字序列号跟踪制造的组件,这为我们提供了一个自然密钥。如您所料,我们选择的类型亲和力是TEXT。这些组件是应用程序的核心,因此有许多表通过此序列号上的外键关系链接。
在一个特定表上,序列号FOREIGN KEY 列的类型关联被错误地声明为INTEGER。由于类型关联系统的灵活性,这从未成为问题,因为我们能够毫无问题地将 INSERT TEXT 值放入列中。一切似乎都运行良好。
随着数据库适度增长,一些查询变得非常缓慢,在现代 PC 上大约为几秒钟。在确保由于FOREIGN KEY 和PRIMARY KEY 声明所有相关列已经被自动索引后,我找到了罪魁祸首。将坏表上的类型亲和性从INTEGER 更改为TEXT* 后,加入该表的慢查询速度加快了两个数量级。
我对最终结果很满意,但我很想知道为什么会这样?由于声明的类型亲和性,SQLite 是否在底层构建了不同类型的索引?比较中类型亲和性的差异是否会阻止查询使用索引?是否有一些不必要的类型转换导致速度变慢?
这是一个例子:
CREATE TABLE IF NOT EXISTS pcb_units (
serial_no TEXT NOT NULL,
PRIMARY KEY (serial_no)
);
CREATE TABLE assembly_pcb_units (
pcb_serial_no INTEGER NOT NULL, -- This is the bad column
assembly_serial_no TEXT NOT NULL,
added_time TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
added_by TEXT NOT NULL,
CONSTRAINT pcb_in_one_assembly_only
UNIQUE(pcb_serial_no),
FOREIGN KEY (assembly_serial_no)
REFERENCES assembly_units(assembly_serial_no),
FOREIGN KEY (pcb_serial_no)
REFERENCES pcb_units(serial_no),
FOREIGN KEY (added_by)
REFERENCES sti_users(user_id)
);
* 我真的希望 SQLite 支持 ALTER TABLE。事实上,我不得不禁用外键约束,删除表,重新创建它,然后重新插入所有行。
【问题讨论】:
-
请显示一个示例数据库架构。
-
添加了示例架构。
-
外键约束不添加任何索引。请显示新旧表查询的 EXPLAIN QUERY PLAN 输出。
-
哇,你说得对。我不知道我从哪里得到他们这样做的想法。即使没有外键上的索引,我的查询目前也在相当合理的时间内运行。我想我会在子键上添加一些索引,看看会有什么不同..
-
其实我改变了主意。文档 (sqlite.org/foreignkeys.html#fk_indexes) 说没有自动索引,但似乎实际上有: SELECT * FROM sqlite_master WHERE name LIKE '%autoindex%';
标签: sql sqlite join types foreign-keys