我正在尝试从匹配查询的表中删除一堆行。我的查询的一般形式是:
DELETE FROM mytable WHERE _id IN (SELECT _id FROM mytable WHERE ...);
该_id
列是一个SERIAL PRIMARY KEY
.
如果我自己运行内部SELECT
查询,它会在大约 1 秒内运行并返回大约 100,000 行。但是,当我将DELETE
调用添加到它时,它似乎只是坐下来大口大口地走开。大口大口地走开。我让它运行了大约一分钟左右,然后假设没有取得任何进展就取消了它。
我添加EXPLAIN ANALYZE
到它的前面,看看我是否可以检查什么花了这么长时间,但那个电话也挂了很长时间。
任何人都可以告诉我可能会发生什么,以便可以非常快速地识别我想要删除的行,但需要不确定的时间来删除它们?
更新:完整查询如下。
DELETE FROM cards
WHERE _id IN (
SELECT _id
FROM cards
LEFT JOIN game_results ON game_results.card_id = cards._id
WHERE NOT available
AND game_id IS NULL
)
Run Code Online (Sandbox Code Playgroud)
表格的简化版本是:
CREATE TABLE cards (_id INTEGER PRIMARY KEY, available BOOLEAN);
CREATE TABLE games (_id INTEGER PRIMARY KEY);
CREATE …
Run Code Online (Sandbox Code Playgroud) 我一直在深入研究我们生产的 PostgreSQL 9.6 数据库的大小,并发现了一些我认为令人惊讶的结果。
我们有一个foos
包含大约1000 万条记录的表(我们称之为)。主键是一个integer
. 我们在这个表上有一个 B 树索引,用于将可选外键插入另一个表(我们称之为bars
)。让我们调用 index index_foos_on_bar_id
。bars.id
只是一个integer
数据类型列。
当我使用\di+
meta 命令查看索引大小时,我发现它占据了大约1GB的空间。一些粗略的计算意味着索引中的每个条目因此需要大约 1GB / 1000 万 =每行 100 字节的空间。
foos
表上几乎没有发生删除,所以膨胀是不存在的。
在我看来,索引将有效地包含诸如将索引列映射到相关表的主键的排序数字对之类的内容。但是,由于它只是integer
类型,因此每行仅使用大约 4 + 4 = 8 个字节,这与实际占用的每行 100 个字节相差甚远。我想它是一个树结构的事实可能会稍微提高一点,但超过 10 倍的差异对我来说有点令人惊讶。
索引使用的所有这些“额外”空间的原因是什么?