假设我在 Postgres (11.3) 中有一个简单的表:
create table posts
(
id serial not null,
created_at timestamp(0)
constraint posts_pkey
primary key (id)
);
Run Code Online (Sandbox Code Playgroud)
如果用户请求 id=5869,我需要能够在按列排序的查询中返回该行之前的 N 行和之后的 N 行created_at。如果我们能够假设 越大id,则 越大created_at,我们可以做一些相对简单的事情,如下所示:
(select * from posts where id < 5869 order by id limit 10)
union all
(select * from posts where id >= 5869 order by id limit 11);
Run Code Online (Sandbox Code Playgroud)
但是,我无法假设更高的 id 是最近创建的,我想知道在这种情况下检索该数据的最佳方法是什么。此方法有效,但在 100k 行数据集上速度非常慢:
WITH
boundaries AS (
SELECT *,
row_number() OVER (ORDER BY created_at DESC) AS …Run Code Online (Sandbox Code Playgroud) 我对 PostgreSQL 管理还比较陌生,我正在尝试了解具体的细节。我的问题是,假设我不需要灾难恢复并且我没有通过设置打开归档archive_mode = on,Postgres 是否有内部机制可以将 WAL 文件轮换出来pg_xlog?如果有,频率是多少?
稍微不同的是,设置archive_mode = on但不配置archive_command- 是否存在 Postgres 将尝试存档到的默认位置?
我无法ON CONFLICT处理外键为复合的外键列。这是一个例子。
create table foreign_table (
id_a text not null,
id_b text not null,
id integer primary key,
constraint ft_a_b_key unique (id_a, id_b)
);
create table my_table (
id integer,
ftable_id_a text,
ftable_id_b text,
constraint my_table_a_b_fk
foreign key (ftable_id_a, ftable_id_b) references foreign_table (id_a, id_b)
);
Run Code Online (Sandbox Code Playgroud)
使用此查询:
insert into tcell_test.my_table (id, ftable_id_a, ftable_id_b)
values (3, 'a3', 'b3') on conflict do nothing ;
Run Code Online (Sandbox Code Playgroud)
比如说,'a3'不在 中foreign_table,我希望ON CONFLICT能够处理该错误。
相反,我收到错误:
Run Code Online (Sandbox Code Playgroud)[23503] ERROR: insert or update on table …
我试图了解什么是 TID 以及它是如何工作的。我在文档中找到了TID的2个定义:
1)来自https://www.postgresql.org/docs/11/datatype-oid.html
系统使用的最终标识符类型是tid,或元组标识符(行标识符)。这是系统列 ctid 的数据类型。元组 ID 是一对(块编号、块内的元组索引),用于标识行在其表中的物理位置。
2)来自https://www.postgresql.org/docs/11/storage-page-layout.html
事实上,PostgreSQL 创建的每个指向项目的指针(ItemPointer,也称为 CTID)都由页码和项目标识符的索引组成。
我理解第二个定义,它对我来说很清楚,但我对第一个定义及其使用的术语感到困惑。
block 中的块索引和元组索引是什么?它们如何与页面和第二个定义匹配?
请帮助并澄清哪个定义是正确的以及我应该如何理解第一个定义中的术语。
我在谷歌上搜索了很多,但没有找到解决方案,我不确定我在这里缺少什么。
我的目的是将此过程中的通知、信息存储到存储在日志目录中的 postgres 日志(txt 文件)中。
在postgres中,我写了一个简单的过程,如下所示。 - - 程序 - - -
create or replace procedure log_debug_info()
language 'plpgsql'
as $body$
begin
raise notice 'Test notice';
raise info 'Test info';
raise log 'test log';
raise debug 'test debug';
end;
$body$
Run Code Online (Sandbox Code Playgroud)
---结束------ 这是我对日志的配置。
#------------------------------------------------------------------------------
# REPORTING AND LOGGING
#------------------------------------------------------------------------------
# - Where to Log -
log_destination = 'stderr' # Valid values are combinations of
# stderr, csvlog, syslog, and eventlog,
# depending on platform. csvlog
# requires logging_collector to be on. …Run Code Online (Sandbox Code Playgroud) 我正在探索建立一个涉及国际象棋位置分析的网站的想法。国际象棋位置本身使用称为 FEN 的格式进行描述,例如,棋盘的起始位置可以描述为:
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
Run Code Online (Sandbox Code Playgroud)
我对如何建模的想法特别感兴趣的部分是直到第一个空间的所有内容。这描述了棋盘从第一级到第八级的每一级的布局。棋子使用字母和大写/小写的组合来描述,以表示棋子类型以及它是否属于黑人玩家(小写)或白人玩家(大写)。整数8表示空格的数量。像 1.e4 这样的移动之后
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1
Run Code Online (Sandbox Code Playgroud)
现在您可以看到第 5 阶部分如何描述 4 个空格,一个白色棋子,然后是 3 个空格。
那么我们如何在像 Postgres 这样的关系数据库中对此进行建模呢?我幼稚的方法是首先将整个 FEN 字符串存储为 a varchar,但是,将来,我想将其迁移到一个结构,使我能够轻松搜索国际象棋位置中的结构。一个例子是,找到数据库中白棋占据 e4 和 e5 位置的所有位置(第 5 个位置的等级段:)3PP3。
FEN 字符串的正则表达式搜索可以找到我感兴趣的位置,但是简单地索引 FEN 列就足够了吗?我是否应该考虑将董事会的每个等级存储为单独的列?或者整个棋盘可以以某种方式表示为矩阵。
我有一个简单的查询:
SELECT a.name AS a_name,
b.description AS b_description
FROM a
JOIN b ON a.id = b.a_id
WHERE b.table_name IS NULL;
Run Code Online (Sandbox Code Playgroud)
(为保护无辜者,化名)
这通常需要大约 3 毫秒才能运行。有时,此查询会挂起。目前已经挂了3天了。幸运的是,我可以暂时尝试在当前状态下对其进行调试。看起来没有任何东西阻止它(通过查询 pg_locks 和 pg_stat_activity 发现),尽管它阻止了其他事情。
即使其他查询处于挂起状态,我也可以再次运行相同的查询,并且它在预期的时间段内成功完成。
可能涉及的事情:我们目前有两个转储数据库的 cron 作业(不要问)。如果可能相关,我可以找到正在运行的确切命令。
任何有关如何调试此问题的建议都将不胜感激!
我正在运行一个查询,例如
select id from students where school_id='67153fb1-8f79-441d-a747-ca3778cf6d3d';
Run Code Online (Sandbox Code Playgroud)
在桌子上看起来像
Table "public.students"
Column | Type | Modifiers
-------------------+-----------------------------+------------------------------------
id | uuid | not null default gen_random_uuid()
school_id | uuid |
Indexes:
"students_pkey" PRIMARY KEY, btree (id)
"students_school_id_idx" btree (school_id)
Run Code Online (Sandbox Code Playgroud)
select 语句的查询计划与 where 类似,如下所示:
explain select id from students where school_id='67153fb1-8f79-441d-a747-ca3778cf6d3d';
QUERY PLAN
--------------------------------------------------------------------------------------------------
Bitmap Heap Scan on students (cost=581.83..83357.10 rows=24954 width=16)
Recheck Cond: (school_id = '67153fb1-8f79-441d-a747-ca3778cf6d3d'::uuid)
-> Bitmap Index Scan on students_school_id_idx (cost=0.00..575.59 rows=24954 width=0)
Index Cond: (school_id = '67153fb1-8f79-441d-a747-ca3778cf6d3d'::uuid)
Run Code Online (Sandbox Code Playgroud)
这相当快。
现在我们将 …
我一直在研究“查看”时间的不同方式以及如何在 Postgres 中正确映射它,但我仍然不确定实际使用什么。有几篇文章建议或者更确切地说说服您将日期存储为timestamp with time zone,而不是存储为 just timestamp。我尤其在夏令时方面遇到困难。
我的用例是一个简单的面向最终用户的应用程序,只能由“欧洲/柏林”时区的人员访问。用户撰写的帖子会与创建和更新的时间戳一起存储。
假设用户在 上发布了帖子2020-01-01T10:00:00+01。如果用户现在在同一天阅读该帖子,它应该显示posted on 1st of January at 10 am。如果同一篇文章7 月在柏林被点击,它仍然应该显示posted on 1st of January at 10 am“无论夏令时如何”。
我的直觉是将时间存储为 a timestamp without time zone,否则 Postgres 会将该时间转换为 UTC 并以这种方式存储。稍后我将无法参考该帖子发布的实际时区。在这种情况下,它会显示为posted on 1st of January at 11 am(由于柏林现在提前两个小时),如果作者要检查最初的时间,这可能会让他们感到困惑发表了这篇文章。
我的想法是否正确,我是否发现了不使用的极端情况之一timestamp with time zone,或者我在这里错过了一些重要的东西?
专门运行 PostgreSQL 11.2 服务器(带有 TimescaleDB 扩展)的 Ubuntu 18.04 服务器将很快耗尽磁盘空间,因此需要向计算机添加新的 SSD 磁盘以支持不断增长的数据库大小。
数据预计将以相同/更高的速率继续增加,因此需要不断增加存储硬件,直到机器用完 2.5 英寸驱动器托架。只有这时才会考虑将数据库分布在多台机器上,因为所涉及的复杂性增加。
想法
联合文件系统mergerfs可以将驱动器集中在一起,轻松解决存储扩展问题。但这会增加数据库操作的延迟,因此不建议这样做。可以通过底层 RAID-1/5/6/10 或使用 SnapRAID 添加冗余。
RAID-0 和 RAID-10 允许将 RAID 阵列扩展到新添加的驱动器中,并通过条带化提高性能。然而,每个添加的驱动器都会增加一个故障点。此外,许多人声称镜像 SSD 的用途有限,因为RAID-0 中的两个 SSD 可能会同时发生故障。所以也许这意味着 RAID-10 并不比 RAID-0 更好。此外,故障率随着每增加一个 SSD 而线性增加。
RAID-5/6 由于奇偶校验计算和写入 2 个驱动器而降低了性能,从而使有效 IOPS 降低了 75%。对于数据库来说似乎是一个糟糕的选择。
PostgreSQLTABLESPACES可用于将每个表分配到特定驱动器。然而,使用表空间会使恢复变得非常复杂。此外,是否可以在新驱动器上创建新表空间并让 Postgres 自动决定将新记录写入何处?
ZFS、BTRFS?对他们不熟悉,愿意探索他们是否合适。
问题: 2020年推荐的PostgreSQL机器扩容方法是什么,如果扩容频繁(一年1-2次),性能应该不会受到太大影响,恢复也不会太复杂可能会导致数据丢失?
RAID-10 对我来说似乎是一个好主意,但 RAID-1 的使用似乎有限,同时会导致“损失”一半的磁盘空间,随着驱动器数量的增加,故障点也会增加,情况会变得更糟。
由于预算限制,我们无法一次性将 2U 机箱中的 16 个驱动器托架全部装满 SSD,因此必须逐步完成。
任何意见是极大的赞赏!
编辑:在研究了 ZFS 之后,这似乎可能是我的案例的解决方案之一。
仅包含镜像 ZFS vdev(每个 …
postgresql ×10
archive-log ×1
exception ×1
foreign-key ×1
logs ×1
raid ×1
scalability ×1
tablespaces ×1
timescaledb ×1
timestamp ×1
timezone ×1