小编vib*_*blo的帖子

为什么 CTE 比内联子查询差很多

我试图更好地了解查询计划器在 postgresql 中的工作方式。

我有这个查询:

select id from users 
    where id <> 2
    and gender = (select gender from users where id = 2)
    order by latest_location::geometry <-> (select latest_location from users where id = 2) ASC
    limit 50
Run Code Online (Sandbox Code Playgroud)

它在我的数据库上运行不到 10 毫秒,用户表中有大约 50 万个条目。

然后我认为为了避免重复的子选择,我可以将查询重写为 CTE,如下所示:

with me as (
    select * from users where id = 2
)
select u.id, u.popularity from users u, me 
    where u.gender = me.gender
    order by  u.latest_location::geometry <-> me.latest_location::geometry ASC
    limit 50;
Run Code Online (Sandbox Code Playgroud)

然而,这个重写的查询运行在大约 1 秒内!为什么会发生这种情况?我在解释中看到它不使用几何索引,但是可以做些什么吗?谢谢! …

postgresql optimization postgresql-9.3

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

无需停机即可从已删除的列中回收磁盘空间

我在 PostgreSQL 数据库中有一个大量使用的表(大约有 500 万行),我想在其中删除一列并回收该列使用的空间。

文档建议进行表重写ALTER TABLE以强制返回空间,但这在使用表时运行并不安全,并且会导致停机。是否有任何不需要停机的实用选项?我试图运行该pgcompact工具,但这并没有改变任何东西。

postgresql disk-space ddl vacuum postgresql-9.3

9
推荐指数
1
解决办法
3555
查看次数

PostgreSQL:在负载下添加或删除列给出错误的列数错误

我有一个经常使用的 PostgreSQL 数据库。有时我需要添加/删除列,最好不要中断任何服务。

我遵循https://www.braintreepayments.com/blog/safe-operations-for-high-volume-postgresql 中的安全操作列表,但是当更新更繁忙的表时,许多操作无论如何都会引起麻烦。

通常,我们为所有操作提供用户定义的函数,这些函数以以下方式运行:

表和函数定义:

create table a(
    id serial primary key,
    x integer
);

create or replace function select_a() returns setof a AS
$$
begin
    return query
    select a.* from a;
end;
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)

然后实际查询由我们的应用程序运行

SELECT id FROM select_a();
Run Code Online (Sandbox Code Playgroud)

但是,如果我ALTER TABLE users ADD COLUMN y text;在系统负载不足的情况下添加一列,我有时(系统承受的负载越频繁和持续越多)会出现这样的错误

错误 #42804 查询结构与函数结果类型不匹配:返回的列数 (2) 与预期的列数 (3) 不匹配。

是否可以以某种方式避免这种情况,或者我是否需要在此类更改期间使系统脱机?

要重新创建它,请按照下列步骤操作:

  1. 创建上面的表格和函数
  2. 创建一个文件 loop_alter.sql

    #!/usr/bin/env bash
    for i in {0..1000}; do
    echo "alter table a add column y …
    Run Code Online (Sandbox Code Playgroud)

postgresql ddl postgresql-9.3

6
推荐指数
1
解决办法
523
查看次数