标签: postgresql

避免冗余聚合函数和/或按列分组的最佳方法

假设我有两个表:

福:

id
baz
Run Code Online (Sandbox Code Playgroud)

酒吧:

id
foo_id
boom
Run Code Online (Sandbox Code Playgroud)

所以一个 Foo 有很多 Bars。我经常发现自己需要为给定的一组 Foo 计算跨条的聚合,但我也想要一些来自 Foo 的属性。这样做的两种最直接的方法是丑陋的:

方法#1:不必要的聚合函数

select
  foo.id,
  min(foo.baz) as baz,
  min(bar.boom) as min_boom
from
  foo
join
  bar on foo.id = bar.foo_id
group by
  foo.id;
Run Code Online (Sandbox Code Playgroud)

方法#2:不必要的按列分组

select
  foo.id,
  foo.baz,
  min(bar.boom) as min_boom
from
  foo
join
  bar on foo.id = bar.foo_id
group by
  foo.id,
  foo.baz;
Run Code Online (Sandbox Code Playgroud)

当 Foo 除了“id”之外只有一个额外的列时,这并不是那么糟糕,但是如果需要包含许多列,那么分组的效率就会大大降低。像这样的查询解决了这两个问题,但似乎很笨拙:

select
  foo.id,
  foo.baz,
  x.min_boom
from
  foo
join
  (select
    foo_id, 
    min(boom) as min_boom
  from
    bar
  group by
    foo_id) x on x.foo_id = foo.id; …
Run Code Online (Sandbox Code Playgroud)

postgresql performance subquery postgresql-9.3 query-performance

7
推荐指数
1
解决办法
6749
查看次数

是否可以将一个表的两个副本无缝地聚集在不同的排列中?

我有一个大约有 100M 行的表。它每天只插入一次数据,但我们需要做select很多事情。该selects为通常比较简单,但需要有时返回几千行的100S。

它基于三列node_id,是唯一的pricedatehour分别是整数、时间戳、整数。大多数查询都很慢,但我将它聚集到node_idpricedate这解决了大多数查询的缓慢问题。这些查询属于以下类型:

select * from mytable where node_id in (1,2,3,4)
Run Code Online (Sandbox Code Playgroud)

我们仍然偶尔需要做这样的查询:

select * from mytable where pricedate>='2016-05-01'
Run Code Online (Sandbox Code Playgroud)

这些仍然很慢,因为它是由node_id第一个聚集的。我们已经有了一个索引pricedate。问题是用户通常需要足够的数据,查询引擎会抛出索引并使用 seq 扫描。一旦它使用了 seq 扫描,它就会从以查询方式对数据进行聚类中受益匪浅。这导致了我遇到的问题,其中一些查询从一个聚类中受益,而其他查询从另一个中受益:

如果有一种方法可以拥有表的两个物理副本,其中一个副本以一种方式聚集,另一个以另一种方式聚集,但用户对它的访问似乎只有一张表,并且数据库引擎将确保它们是同步的。显然,这样做会受到写入处罚,但这对我们的使用来说无关紧要。

这样的事情可能吗?

我猜没有一种内置的方式来做我所描述的。无论如何,我想我会mytable_dup使用相同的唯一键约束调用一个表,但使用备用集群,然后设置触发器在插入/更新/删除主服务器时插入它。这似乎可行,但从这里开始,是否有一种合理的方法select可以有效地从复制表中提取?

我在家里运行 PostgreSQL 9.4,在 Google 上运行 9.5。

postgresql performance query-performance

7
推荐指数
1
解决办法
72
查看次数

使用与源数据库相同的语言环境设置还原 PostgreSQL 数据库

我在Ubuntu 14.04 LTS生产机器上有一个 PostreSQL 9.x 数据库。我的开发机器是基于Windows 7的,提供 PostreSQL 9.y。

我想在我的开发机器上恢复 Ubuntu PostreSQL 数据库。

我注意到 Ubuntu 数据库使用以下语言环境设置:

  • 字符集编码=UTF8
  • 整理顺序,字符串排序顺序=en_US.UTF-8
  • 字符类型,字符分类=en_US.UTF-8

当我在没有指定语言环境的情况下在 Windows 机器上恢复数据库时,它将被设置为

  • 字符集编码=UTF8
  • 整理顺序,字符串排序顺序=German_Germany.1252
  • 字符类型,字符分类=German_Germany.1252

我的计划是让我的开发机器上的数据库尽可能类似于我的 Ubuntu 机器上的数据库。所以我的想法是首先在我的 Windows 机器上创建一个具有生产匹配语言环境的数据库,然后将我的 Ubuntu 数据库prod-db.backup备份文件恢复到该创建的数据库中:

createdb --host=localhost --username=postgres --encoding=Unicode --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8 --owner=prod prod-db
pg_restore --host=localhost --username=postgres --format=custom prod-db.backup --dbname=prod-db
Run Code Online (Sandbox Code Playgroud)

这个想法不起作用,因为createdb在 Windows 上会抱怨错误无效的语言环境名称 en_US.UTF-8

我去了一个狩猎找到Windows区域名称相匹配的Ubuntu的语言环境名称,其中包括使用的解决方案template0中模板的数据库,不同的区域设置标识符,如实验en_US.UTF-8 …

postgresql pg-restore

7
推荐指数
1
解决办法
8979
查看次数

查找列中最常用的非停用词

简而言之,我有一个包含普通散文的 Postgres 列,我想确定所有行中x最常用的单词(“单词”是由空格分隔的一组字符,但不是停用词)。

我找到了两个几乎达到目标的解决方案:

SELECT *                                       
FROM   ts_stat($$SELECT to_tsvector('english', title) FROM item$$) 
ORDER  BY ndoc DESC
LIMIT  50;
Run Code Online (Sandbox Code Playgroud)

这很好,除了它返回词干。

SELECT   UNNEST(string_to_array(title, ' ')) AS word, COUNT(*) AS ct
FROM     item 
GROUP    BY 1 
ORDER    BY 2 DESC
LIMIT    50;
Run Code Online (Sandbox Code Playgroud)

这个返回完整的词,但包括停用词。

为简单起见:应该在 上找到停用词TABLE stop_words (lowercase_stopword text PRIMARY KEY)

有人可以帮我上网吗?

postgresql full-text-search string-manipulation

7
推荐指数
2
解决办法
2542
查看次数

平均年龄的天数的含义?

我想知道我的用户的平均年龄并执行以下操作:

# SELECT avg(age(birthday)) FROM "user";
                   avg
------------------------------------------
 33 years 10 mons 32 days 08:33:10.577946
Run Code Online (Sandbox Code Playgroud)

天数是什么意思?怎么可能超过31天?

我有 3746 条记录,而且我在 UTC 时区。

PS:我使用的是 Postgres 9.5.3

postgresql

7
推荐指数
1
解决办法
742
查看次数

如何使用 EXECUTE 在动态 SQL 中使用函数参数?

我在 PostgreSQL 9.5 中编写了一个 PL/pgSQL 函数。它编译得很好,但是当我从 pgAdmin3 调用它时,它给了我一个错误。似乎用函数中传递的参数替换列的动态查询不起作用。

下面是我的功能:

CREATE OR REPLACE FUNCTION insertRecordsForNotification(username text, state     text, district text, organizationId text, bloodGroup text, status text,   approveRejectStatus text, emailSubject text, emailBody text, notificationStatus text) RETURNS boolean AS $$
DECLARE
id int;
r moyadev.user%rowtype;
_where text :=
  concat_ws(' AND '
    , CASE WHEN state IS NOT NULL THEN 'state = $2' END
    , CASE WHEN district IS NOT NULL THEN 'district = $3' END
    , CASE WHEN bloodGroup IS NOT NULL THEN …
Run Code Online (Sandbox Code Playgroud)

postgresql dynamic-sql parameter plpgsql postgresql-9.5

7
推荐指数
1
解决办法
3万
查看次数

Postgres 无法从客户端接收数据:连接超时

我是 sql DBA,正在学习 postgres ..在 postgres 日志中,我经常收到“无法从客户端接收数据:连接超时”我没有除此之外的任何其他日志

不知道如何排除故障?我检查了应用程序日志和 DBs 日志以比较时间,但我没有注意到任何异常。

有人可以指导我如何追踪这个问题。

谢谢

postgresql timeout

7
推荐指数
1
解决办法
3万
查看次数

具有 AT TIME ZONE 和 UTC 偏移量的奇数

我不明白这两列之间的区别。美国/芝加哥时区是 UTC-6,所以我希望两者都返回相同的结果:

select timezone('America/Chicago', '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC'),
       timezone('UTC-6'          , '2017-01-01 12:00:00'::TIMESTAMP AT TIME ZONE 'UTC');
Run Code Online (Sandbox Code Playgroud)

然而,结果是:

2017-01-01 06:00:00 | 2017-01-01 18:00:00
Run Code Online (Sandbox Code Playgroud)

而且,这种行为非常尴尬,

SELECT '1:00 -1'::time with time zone AT TIME ZONE '-1'; 
  timezone   
-------------
 03:00:00+01
Run Code Online (Sandbox Code Playgroud)

谁能解释一下?

postgresql timestamp utc-time timezone

7
推荐指数
1
解决办法
3050
查看次数

如何在减少膨胀或 ALTER (ing) 表的同时最小化访问独占表锁?

在某些情况下,我被告知不要对生产中的表执行 VACUUM FULL(或 CLUSTER),因为这将独占锁定它的时间比预期的要长。这同样适用于几个 ALTER TABLE 操作(例如更改几个列的类型)。

提出的替代方案始终是执行以下操作:

 CREATE TABLE new_table AS SELECT * FROM old_table ;
 -- recreate all indices and constraints
 ALTER TABLE old_table RENAME TO going_to_drop_table ;
 ALTER TABLE new_table RENAME TO old_table ;
 DROP TABLE going_to_drop_table ;
Run Code Online (Sandbox Code Playgroud)

这适用于没有依赖关系的场景old_table(意味着没有任何依赖它的视图,也没有任何外键约束、函数等),并且old_table没有任何插入或更新。但在大多数数据库中,这将是一个例外,而不是规则。

有没有办法在不丢失依赖关系的情况下进行这样的“表交换”?

[为了完整起见:我对如何为 PostgreSQL 9.5 或 9.6 做这件事特别感兴趣]


研究到现在(关于根本原因):

  1. 是否可以在 Postgres 中异步运行 VACUUM FULL?=> pg_repack。注意事项:在 Windows 上可能不容易实现,未使用 postgresql 9.6 进行测试。看起来是最有希望的选择。
  2. pg_reorg: 类似于 pg_repack(是它的基础)=> 自 postgresql 9.4 以来似乎没有更新,并且它主要被pg_repack.
  3. 来自 …

postgresql optimization maintenance online-operations postgresql-9.6

7
推荐指数
0
解决办法
690
查看次数

多列时间戳索引上的 min()/max()

我发现很难理解为什么在这个查询中进行了一堆堆提取。据我了解,当索引中没有空值(两端)时,反向搜索索引应该与直接搜索一样快,反之亦然。

我怀疑向前/向后扫描实际上是一个红鲱鱼,但我无法识别此解释输出中的任何其他有意义的差异。

这是表格布局。我已将我认为与问题无关的前两列匿名化,但为了完整起见,我保留了它们及其索引。

testqueuedb=> \d+ queue
                                                                  Table "public.queue"
        Column         |           Type           |                          Modifiers                          | Storage  | Stats target | Description
-----------------------+--------------------------+-------------------------------------------------------------+----------+--------------+-------------
 foo                   | character varying(64)    | not null                                                    | extended |              |
 bar                   | numeric(6,0)             | not null                                                    | main     |              |
 worker                | character varying(32)    | not null                                                    | extended |              |
 queued                | timestamp with time zone | not null default (timeofday())::timestamp without time zone | plain    |              |
Indexes:
    "queue_idx_job" btree (foo, bar, worker)
    "queue_idx_worker" btree (worker, …
Run Code Online (Sandbox Code Playgroud)

postgresql performance postgresql-performance

7
推荐指数
1
解决办法
599
查看次数