就像另一个问题所示,我在 3D 空间中处理了很多(> 10,000,000)个点条目。这些点定义如下:
CREATE TYPE float3d AS (
x real,
y real,
z real);
Run Code Online (Sandbox Code Playgroud)
如果我没记错的话,需要 3*8 字节 + 8 字节填充(MAXALIGN是 8)来存储这些点之一。有没有更好的方法来存储这种数据?在前面提到的问题中,有人指出复合类型涉及相当多的开销。
我经常做这样的空间查询:
SELECT t1.id, t1.parent_id, (t1.location).x, (t1.location).y, (t1.location).z,
t1.confidence, t1.radius, t1.skeleton_id, t1.user_id,
t2.id, t2.parent_id, (t2.location).x, (t2.location).y, (t2.location).z,
t2.confidence, t2.radius, t2.skeleton_id, t2.user_id
FROM treenode t1
INNER JOIN treenode t2 ON
( (t1.id = t2.parent_id OR t1.parent_id = t2.id)
OR (t1.parent_id IS NULL AND t1.id = t2.id))
WHERE (t1.LOCATION).z = 41000.0
AND (t1.LOCATION).x > 2822.6
AND (t1.LOCATION).x …Run Code Online (Sandbox Code Playgroud) 在另一个问题中,我了解到我应该从我的一个表中优化布局以节省空间并获得更好的性能。我这样做了,但最终得到了比以前更大的表,并且性能没有改变。当然我做了一个VACUUM ANALYZE. 怎么会?
(我看到如果我只索引单列,索引大小不会改变。)
这是我来自的表(我添加了尺寸 + 填充):
Table "public.treenode"
Column | Type | Size | Modifiers
---------------+--------------------------+------+-------------------------------
id | bigint | 8 | not null default nextval( ...
user_id | integer | 4+4 | not null
creation_time | timestamp with time zone | 8 | not null default now()
edition_time | timestamp with time zone | 8 | not null default now()
project_id | integer | 4 | not null
location | real3d | 36 | …Run Code Online (Sandbox Code Playgroud) 我正在使用 PostgreSQL 9.3。假设我们正在制造某种类型的某些物品,在任何时候我们最多只能生产某种类型的一件物品。下表记录了我们制造物品的历史记录,其中可能有一行manufactured_until是null- 这些是当前生产的物品。
create table item
(
id int,
type_id int,
manufactured_from timestamp,
manufactured_until timestamp
)
Run Code Online (Sandbox Code Playgroud)
样本数据:
1 | 101 | 1.1.2000 | 31.12.2012
2 | 102 | 1.4.2003 | 1.1.2010
3 | 101 | 1.1.2013 |
4 | 102 | 2.1.2010 | 4.5.2014
5 | 102 | 5.5.2014 |
Run Code Online (Sandbox Code Playgroud)
以下逻辑应该成立:对于每种物品类型,此时最多应该生产一个物品 ( manufactured IS NULL)。在示例中,我应该无法添加记录(6, 101, 27.8.2014, NULL)。
我想写一个UNIQUE约束来保护它。是否可以?对于奖励积分,是否有一种相当复杂的方法来保护一种项目类型的间隔不重叠?
postgresql database-design exclusion-constraint unique-constraint
尝试这个:
create table test (f float);
insert into test values (330.0);
commit;
select (8 + 330.0/60)::int; --14
select (8 + f/60)::int from test; --14
select (9 + 330.0/60)::int; --15
select (9 + f/60)::int from test; --14
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么最后一个查询返回 14 而不是 15 吗?
PostgreSQL 9.3.9 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
12.04.5 LTS (GNU/Linux 3.2.0-63-virtual x86_64)
Run Code Online (Sandbox Code Playgroud) 我有一个昂贵的定期 PostgreSQL 9.3 查询,格式如下:
SELECT * from mytable where name NOT LIKE '%foo%';
Run Code Online (Sandbox Code Playgroud)
foo这里实际上是一个永远不会改变的常数。查询开销很大,因为它需要表扫描。我希望实际上只有几行与查询匹配,所以我想使用部分索引来加快查询速度。
CREATE INDEX foo_idx ON mytable ((name NOT LIKE '%foo%')) WHERE name NOT LIKE '%foo%';
Run Code Online (Sandbox Code Playgroud)
但是,当我执行EXPLAIN查询时,它仍然使用顺序扫描而不是依赖新索引。 我究竟做错了什么?
我在CREATE INDEX语句的括号表达式子句中尝试了几种不同的表达式,但没有任何帮助:
CREATE INDEX foo_idx ON mytable (name) WHERE name NOT LIKE '%foo%';
CREATE INDEX foo_idx ON mytable ((name LIKE '%foo%')) WHERE name NOT LIKE '%foo%';
Run Code Online (Sandbox Code Playgroud)
我也尝试删除WHERE索引的子句,但这也无济于事。
postgresql performance index index-tuning postgresql-performance
这显然是一个 SSCCE。
我有一个inventory表格,其中包含numOfItems在任何给定日期 ( inventoryDate)仓库中的物品数量( )。两者都是整数以保持简单:
CREATE TABLE inventory(inventoryDate INTEGER, numOfItems INTEGER);
ALTER TABLE inventory ADD PRIMARY KEY (inventoryDate);
Run Code Online (Sandbox Code Playgroud)
现在我有一些条目:
INSERT INTO inventory(inventoryDate, numOfItems) VALUES(1,250),(2,275)
Run Code Online (Sandbox Code Playgroud)
上面说的是,1仓库里按时有250件物品,按时2有275件。
现在我想测试一下,在最近的日期,仓库中的物品数量是否超过了 1000:
SELECT 1000<(SELECT numOfItems FROM inventory ORDER BY inventoryDate DESC LIMIT 1)
Run Code Online (Sandbox Code Playgroud)
以上似乎有效。但是,在inventory表中根本没有条目的边缘情况下,它不起作用:
DELETE FROM inventory;
SELECT 1000<(SELECT numOfItems FROM inventory ORDER BY inventoryDate DESC LIMIT 1)
Run Code Online (Sandbox Code Playgroud)
...返回:
?column?
(null)
Run Code Online (Sandbox Code Playgroud)
我想将根本没有条目的边缘情况视为表示零 (0) 项。我知道我总是可以inventory用一个值为 0 的假第一个条目来初始化表,但就像我说的这是一个 SSCCE(在我的真实情况下,这个表确实是一个我不想修改的视图)。
所以我最终编写了这样的查询:
WITH cte AS …Run Code Online (Sandbox Code Playgroud) 我正在尝试恢复数据以选择数据库的表 (9.3.5)。这是从生产到测试的数据刷新,同时在测试数据库中维护一些表数据(如应用程序用户表)。我首先截断我计划刷新的表,然后我可以使用以下命令成功恢复 1 个表:
pg_restore -a -d ACMETEST -n public -v -U acme -t hardware /var/acme/backups/restore/ACMEDatabase.bak
,它给出以下响应,紧接着是命令提示符:!pg_restore:连接到数据库进行恢复 pg_restore:处理表“硬件”的数据 pg_restore:设置表数据硬件的所有者和权限
查询显示数据加载成功。
手册页并未表明您可以通过使用数组作为 -t 的输入来一次将数据恢复到多个表中,但我认为这是可能的,所以尝试了这个:
pg_restore -a -d ACMETEST -n public -v -U acme -t hardware,location /var/acme/backups/restore/ACMEDatabase.bak
第二个命令的结果是一行,内容如下:
然后它将我转回命令提示符,就好像命令已完成但没有加载任何数据。
我确实查看了 -L 选项以使用列表文件,但我正在尝试创建一个可重复的过程,该过程可供全国各地数据库上的许多人使用,因此我没有看到从列表中注释掉大量行的过程列表文件为每个还原具有实际成功的机会。我是否必须为我想要恢复的每个单独的表执行第一个命令,或者有什么方法可以将一组表提供给这个命令?
在问这个问题之前,让我先解释一下场景。
我有一个包含一组表的数据库。一个表,比如表 A,包含用户名详细信息,而另一个表,比如表 B,包含用户活动日志。当从表 A 中删除特定用户条目时,我想从表 B 中删除特定用户日志。我可以使用触发器来执行此操作,但要求在某个时间后(例如 5 分钟后)应删除表 B 中的条目),而不是立即。
是否可以将触发器执行延迟 5 分钟?触发器的可能设计是什么。在这种情况下,延迟触发是否会有所帮助。
我有一个总数据大小为 115GB 的 Postgres 数据库。服务器有~60GB 的内存。索引缓存命中率保持在 99% 以上,但表缓存命中率已降至约 97%。
我试图确定是否有我们正在制作的特定查询或访问模式导致下降。如果是这样,我们也许能够优化应用程序。
我使用以下查询来识别命中率低的表...
SELECT relname,
CASE (sum(heap_blks_hit) + sum(heap_blks_read))
WHEN 0 THEN 1
ELSE sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read))
END as hitrate,
pg_size_pretty(sum(heap_blks_hit) + sum(heap_blks_read)) AS total_read,
pg_size_pretty(sum(heap_blks_read)) AS total_miss
FROM pg_statio_user_tables
GROUP BY relname
ORDER BY hitrate
Run Code Online (Sandbox Code Playgroud)
我不知道从这里去哪里。有没有办法跟踪某些查询是否通常会为我知道的表产生未命中数?
下面的选择返回我所有用户拥有的所有项目的数组。
WITH user_projects AS
(SELECT
u.id as user_id
,COALESCE(array_agg(DISTINCT pa.project_id), '{0}'::integer[]) as project_ids
FROM users u
LEFT JOIN project_assignments pa on pa.user_creator_id = u.id
GROUP BY u.id
)
user: 1, project_ids: {1, 2}
user: 2, project_ids: {3, 4}
Run Code Online (Sandbox Code Playgroud)
使用该选择,我想进行报告,该报告将为每个用户显示 12 个月的摘要。
SELECT
to_char(pk.created_at,'Mon') as mon
,extract(year from pk.created_at) as yyyy
,up.user_id
,COALESCE(count(distinct pk.keyword_id), 0) as total_keywords
FROM user_projects up
LEFT JOIN project_keywords pk on pk.project_id = ANY(up.project_ids::int[])
GROUP BY up.user_id, up.project_ids, 1, 2
Run Code Online (Sandbox Code Playgroud)
输出:
mon: sept, yyyy: 2014, user_id: 1, …Run Code Online (Sandbox Code Playgroud) postgresql ×10
datatypes ×2
cache ×1
disk-space ×1
index ×1
index-tuning ×1
integer ×1
join ×1
performance ×1
pg-dump ×1
psql ×1
spatial ×1
trigger ×1
vacuum ×1