这更像是一个通用的 SQL 问题,但如果有人知道 Firebird/Interbase 特定优化,我将使用 Firebird 2.5。首先,以下是一个简化的示例架构,用于说明我要解决的问题:
CREATE TABLE users
(
id INTEGER PRIMARY KEY,
name VARCHAR(16)
);
CREATE TABLE data_set
(
id INTEGER PRIMARY KEY,
name VARCHAR(64)
);
CREATE UNIQUE INDEX data_set_name_idx ON data_set(name);
CREATE TABLE data
(
user_id INTEGER,
data_set_id INTEGER,
data BLOB,
PRIMARY KEY(user_id, data_set_id)
);
CREATE INDEX data_user_id_idx ON data(user_id);
CREATE INDEX data_data_set_id_idx ON data(data_set_id);
我试图运行的查询如下:
SELECT users.name, data_set.name, data FROM users, data_set, data
WHERE user_id=XXX AND user_id=users.id AND data_set_id=data_set.id
ORDER BY data_set.name;
用我想要的user_id填写“XXX”。所以我正在做的是从数据表中选择特定用户拥有的所有行,并根据data_set名称对结果进行排序。
这可以正常工作,但问题是数据表中有超过十亿行,并且data_set表也不小。单个用户 id 的结果集可能有数亿行。发生的情况是,为了使 ORDER BY 工作,数据库必须创建大量临时数据,这些数据非常慢并且使用大量磁盘空间。如果没有 ORDER BY,它会很快,但显然不像我需要的那样排序。
一种解决方案是获取data_set.name值并将它们放在data的 varchar 列中。然后可以将其编入索引并快速排序。这种方法的问题是它会有大量的重复数据并使数据库绝对庞大。
另一种解决方案是索引视图或索引计算列。据我所知,Firebird 都不支持这些。
还有其他想法吗?