此查询获取您关注的人创建的帖子列表。您可以关注无限数量的人,但大多数人关注 < 1000 人。
使用这种查询方式,明显的优化是缓存"Post"id,但不幸的是我现在没有时间这样做。
EXPLAIN ANALYZE SELECT
"Post"."id",
"Post"."actionId",
"Post"."commentCount",
...
FROM
"Posts" AS "Post"
INNER JOIN "Users" AS "user" ON "Post"."userId" = "user"."id"
LEFT OUTER JOIN "ActivityLogs" AS "activityLog" ON "Post"."activityLogId" = "activityLog"."id"
LEFT OUTER JOIN "WeightLogs" AS "weightLog" ON "Post"."weightLogId" = "weightLog"."id"
LEFT OUTER JOIN "Workouts" AS "workout" ON "Post"."workoutId" = "workout"."id"
LEFT OUTER JOIN "WorkoutLogs" AS "workoutLog" ON "Post"."workoutLogId" = "workoutLog"."id"
LEFT OUTER JOIN "Workouts" AS "workoutLog.workout" ON "workoutLog"."workoutId" = "workoutLog.workout"."id"
WHERE
"Post"."userId" IN …Run Code Online (Sandbox Code Playgroud) postgresql performance index optimization postgresql-performance
我有一个旧模式(免责声明!),它使用基于哈希生成的 id 作为所有表的主键(有很多)。这种 id 的一个例子是:
922475bb-ad93-43ee-9487-d2671b886479
Run Code Online (Sandbox Code Playgroud)
改变这种方法是不可能的,但是索引访问的性能很差。撇开这可能的无数原因不谈,我注意到有一件事似乎不太理想 - 尽管所有许多表中的所有 id 值的长度都正好是 36 个字符,但列类型是varchar(36),而不是 char(36)。
将列类型更改为固定长度是否会char(36)提供任何显着的索引性能优势,除了每个索引页的条目数量增加很小等之外?
即在处理固定长度类型时 postgres 的执行速度是否比处理可变长度类型快得多?
请不要提及微小的存储节省 - 与对列进行更改所需的手术相比,这无关紧要。
为了存储 128 位 UUID,有多种存储选项:
从索引的角度来看,哪些是最有效的?如果数据库不支持专用的 uuid 类型,那么 1、2、3 中的哪一个是最佳选择?
假设您有这样的nodes表:
CREATE TABLE nodes
(
node serial PRIMARY KEY,
parent integer NULL REFERENCES nodes(node),
ts timestamp NOT NULL DEFAULT now()
);
Run Code Online (Sandbox Code Playgroud)
它代表了一个标准的类似节点的树结构,根节点在顶部,几个子节点悬挂在根节点或其他子节点上。
让我们插入几个示例值:
INSERT INTO nodes (parent)
VALUES (NULL), (NULL), (NULL), (NULL), (1), (1), (1), (1), (6), (1)
, (6), (9), (6), (6), (3), (3), (3), (15);
Run Code Online (Sandbox Code Playgroud)
现在我想检索前 10 个根节点及其所有子节点,深度为 4:
WITH RECURSIVE node_rec AS
(
(SELECT 1 AS depth, * FROM nodes WHERE parent IS NULL LIMIT 10)
UNION ALL
SELECT depth + 1, n.*
FROM nodes …Run Code Online (Sandbox Code Playgroud) 我有这个UNIQUE限制:
ALTER TABLE table ADD CONSTRAINT "abc123" UNIQUE
("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8");
Run Code Online (Sandbox Code Playgroud)
然后我这样做:
INSERT INTO table ("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8")
VALUES ('a', 'b', 'c', 'd', 'e', 'f', null, true);
INSERT INTO table ("col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8")
VALUES ('a', 'b', 'c', 'd', 'e', 'f', null, true);
Run Code Online (Sandbox Code Playgroud)
两者都有效。两行已添加到表中。从逻辑上讲,第二个应该失败。但事实并非如此。
我究竟做错了什么?这让我发疯。
注意:如果这是我自己的数据,我将拥有一个真正独特的列,而不是这个“疯狂”的UNIQUE约束。问题是这个表保存了我的银行帐户的记录,而且他们愚蠢地在 CSV 转储中没有真正的“唯一”列,我可以用它来实际确保不插入重复的行,所以我有提出一个组合整个表中所有列以确定唯一性的方法。
幸运的是,当我尝试在大长度文本列上创建唯一索引时,Erwin Brandstetter救了我。
插入率的上限是每年数百亿行。
对于我的实现,散列永远不需要离开数据库,但散列数据必须经常与外部数据进行比较才能存在。
根据我针对这些目的进行优化的有限经验,我假设散列的最佳数据类型是bytea. 替代方案当然是更长的十六进制字符串。
bytea这些哈希的最佳数据类型是否正确?
如果bytea不是最优的,什么是最优的?
我的意图应该如何实现?
澄清
我根据 Erwin Brandstetter 的建议使用文本的哈希值,以确保大文本是唯一的。我有限的理解是,原始二进制数据总是性能最好的,尤其是与字符串相比时。
只需比较哈希是否存在即可抢占唯一性违规,因此哈希很高兴永远不需要离开数据库。由于 libpqxx 令人难以置信的设计,看起来好像数据可以简单地通过准备好的语句输入并使用(decode(md5($1::text), 'hex')). 当我更熟悉bytea通过 libpqxx 3.1 插入时,我会将其移至 C++。
对于此实现,冲突是可以接受的,因为可以在不破坏系统的情况下重建数据以符合要求。
如果愉快地达到最大吞吐量,那么应该预期经济资源将可用于容纳它;因此,主要关注点始终是性能,所以如果我对 Postgres 的功能及其分区表处理这些行数的能力的理解是准确的,那么它有望在很长一段时间内成为该工作的正确工具。幸运的是,超过几秒钟的数据永远不会改变,我的理解是 Postgres 分区表可以将这些数据制成碎肉。如果没有,这将是那些好问题之一。
我想弄清楚是否有一种方法可以使嵌套 CTE 适用于这种特殊情况。
考虑以下基于实际应用程序的(高度人为设计的)场景:有一个员工 ID 的单列表。然后是包含所有详细信息的员工属性表。(单列表背后的主要原因通常是理所当然地需要在知道实际员工的任何详细信息之前批量创建和分配新员工 ID。)
现在到手头的任务,我们要为新员工插入详细信息(即姓名),但首先我们需要检查是否已经存在具有该姓名的员工。如果是,我们将简单地返回 id,如果不是,我们将创建一个新的员工记录,然后插入详细信息,最后返回新创建的 id。
要重新创建此测试场景:
CREATE TABLE public.employee (
id text DEFAULT gen_random_uuid(),
PRIMARY KEY (id)
);
CREATE TABLE public.employee_details (
employee_id text,
name text,
PRIMARY KEY (employee_id),
FOREIGN KEY (employee_id) REFERENCES public.employee(id)
);
Run Code Online (Sandbox Code Playgroud)
我试图敲定的查询如下所示。
with
e as
(select name, employee_id from employee_details where name = 'jack bauer'),
i as (insert into employee_details (name, employee_id)
select 'jack bauer',
(with a as (insert into employee values(default) RETURNING id) select a.id from a)
where not exists …Run Code Online (Sandbox Code Playgroud) 我有 8 个使用 UUID 主键的表,其中 7 个使用 UUID 外键。使用 BIGSERIAL 而不是 UUID 对性能会更好吗?
我正在设计一个系统,在该系统中我需要能够使用文件或字符串 SHA3-256 哈希来搜索数据库。
例如,测试的哈希是
36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80
Run Code Online (Sandbox Code Playgroud)
postgresql ×9
index ×5
cte ×2
optimization ×2
performance ×2
uuid ×2
bytea ×1
datatypes ×1
hashing ×1
insert ×1
mysql ×1
null ×1
oracle ×1
order-by ×1
primary-key ×1
recursive ×1
sql-server ×1
varchar ×1