我似乎在中型 RDS 盒子(db.m3.medium,3.7gb ram)上的查询速度很慢。
这是一个包含 4,152,928 行的表格。
select sum(some_field) c
from pages
where pages.some_id=123
and pages.first_action_at > '2014-01-01 00:00:00 +1000'
Run Code Online (Sandbox Code Playgroud)
总运行时间:45031 毫秒。
在本地,我有大约 110 万行,同样的查询需要大约 450 毫秒。
这是查询计划,来自解释:
Aggregate (cost=475640.59..475640.60 rows=1 width=4)
-> Seq Scan on pages (cost=0.00..475266.07 rows=149809 width=4)
Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time zone)
AND (some_id = 447))
Run Code Online (Sandbox Code Playgroud)
这是来自解释分析的回应:
Aggregate (cost=475641.74..475641.76 rows=1 width=4) (actual time=42419.717..42419.718 rows=1 loops=1)
-> Seq Scan on pages (cost=0.00..475267.22 rows=149810 width=4) (actual time=0.013..42265.908 rows=141559 loops=1)
Filter: ((first_action_at > '2014-01-01 00:00:00'::timestamp without time …Run Code Online (Sandbox Code Playgroud) postgresql performance index index-tuning postgresql-performance
我们在 Postgres 9.2.10 数据库中有一个大约有 20 列的表。为了在某些SELECT查询上获得更好的性能,我们计划在数据类型为 的列上添加索引timestamp。由于索引也会降低插入的性能,我们做了以下性能测试:
我们在表中插入了 500 万条记录。那是最大值。我们期望在生产中的记录数。然后我们测量了在时间戳列上插入有索引和没有索引的 10000 条记录的时间。这是我们每天预期的最大插入次数,峰值每秒不超过 5 次插入。
结果如下:
至少对于本次测试,该指数仅略微降低了性能。对于我们的要求,我没有看到添加索引的问题。
但这只是实验室环境中的一项测试,在生产数据库上运行时是否还有其他陷阱?我们是否会遇到INSERT在特定情况下突然需要超过 5 秒的情况?
我们在查询生产数据库中的表时遇到问题。一个文本列将与我们在 where 子句中过滤的字符串相等,但 postgres 不会选择该行。(我们在 postgres 11.11 上)我们的表设置如下:
(PROD)=> \d names;
Table "public.names"
Column | Type | Collation | Nullable | Default
----------------------+-----------------------------+-----------+----------+---------
name | text | | not null |
processed_name | text | | not null |
name_index | integer | | not null |
when_created | timestamp without time zone | | not null |
Indexes:
"names_pkey" PRIMARY KEY, btree (name, processed_name)
"names_name_index_key" UNIQUE CONSTRAINT, btree (name_index)
"ix_names_name" btree (name)
"ix_names_processed_name" btree (processed_name)
Run Code Online (Sandbox Code Playgroud)
当我们处理名称列表时,我们会检查它们是否已经在表中,以防止重复添加和违反主键约束。
然而,在一个名字上,'?????? ????????? ???????',查看名称是否已经存在的查询返回一个空集, …
我有一个分区表...
CREATE TABLE erco.rtprices
(
scedtime timestamp with time zone NOT NULL,
node_id integer NOT NULL,
lmp numeric(12,6),
CONSTRAINT rtprices_pkey PRIMARY KEY (scedtime, node_id)
) PARTITION BY LIST (node_id);
Run Code Online (Sandbox Code Playgroud)
每个都有node_id自己的分区。
如果我进行直接查询(第一个版本),例如:
explain select scedtime, lmp
from erco.rtprices
where node_id = 11111
Run Code Online (Sandbox Code Playgroud)
然后该计划仅对rtprices_11111分区进行顺序扫描。 这就是我要的。
但是,如果我执行(第二个版本)查询,例如
explain select scedtime, lmp
from erco.rtprices
inner join erco.nodes using (node_id)
where nodename = 'somename'
Run Code Online (Sandbox Code Playgroud)
那么该计划包括对每个分区进行顺序扫描,即使此查询与第一个查询一样有限制。
我尝试了上述查询的另一种形式(第三个版本)。
explain select scedtime, lmp
from erco.rtprices
where node_id = (select node_id from erco.nodes where nodename='somename') …Run Code Online (Sandbox Code Playgroud) postgresql execution-plan partitioning postgresql-performance postgresql-13
我们在 CentOS 6.5 上运行 Postgres 9.4.4 并且有一个已经工作多年的 SELECT 查询,但在我们从 9.2 升级后停止工作并挂起(花了一段时间才注意到它,所以我不知道它是否是我们升级与否后立即)。
SELECT id || ':' || group_number AS uniq_id
FROM table_one
WHERE id || ':' || group_number NOT IN (
SELECT id || ':' || group_number
FROM table_two
)
AND id NOT IN (
SELECT id
FROM table_three
WHERE timestamp > NOW() - INTERVAL '30 days'
AND client_id > 0
);
Run Code Online (Sandbox Code Playgroud)
在所有表中id都是一个整数,但存储为character varying (15)(旧系统)。group_number存储为smallint.
table_two 的子查询返回大约 250 万条记录。的子查询table_three返回大约 2,500 条记录。如果单独运行,两者都在大约 …
说,我有一个表格,代表编号框中的彩色和标记的项目。
每个盒子不能包含多个带有特定标签的物品,但具有相同标签(以及相同或不同颜色)的物品在其他盒子中可能是唯一的。
过度简化,使用 PostgreSQL,我们可以得到下表:
CREATE TABLE items (
label character varying,
color character varying,
box_number integer
);
INSERT INTO items VALUES
('a','red',1),
('b','blue',1),
('c','blue',1),
('a','red',2),
('c','green',2),
('d','blue',2),
('b','red',3),
('d','green',3);
Run Code Online (Sandbox Code Playgroud)
我想知道编号为 3 的箱子内所有物品的标签和颜色,以及可以找到具有相同标签的物品的所有箱子编号。换句话说,我试图:
SELECT label, boxes
FROM (
SELECT label, array_agg(DISTINCT box_number) AS boxes
FROM items
GROUP BY label
) AS sub1
WHERE 3 = ANY(boxes);
Run Code Online (Sandbox Code Playgroud)
但我还需要返回color列,仅显示框号 3 内项目的颜色。
对于示例数据,输出应该是这样的:
标签 | 颜色 | 盒子 ------+-------+------ 乙 | 红色 | 1,3 d | 绿色| 2,3
我们有一个包含约 50 亿行的 PostgreSQL 表,它养成了一个讨厌的习惯,即缺少正确的索引并对某些LIMIT操作进行主键扫描。
问题通常出现在一个ORDER BY .. LIMIT ..子句(Django 分页中的常见模式)上,其中LIMIT是索引匹配的结果的一些相对较小的子集。一个极端的例子是这样的:
SELECT * FROM mcqueen_base_imagemeta2
WHERE image_id IN ( 123, ... )
ORDER BY id DESC
LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
其中该IN子句中的项目约为 20,索引匹配的总行数image_id为 16。
在EXPLAIN表明,它错过了image_id指数,而是确实5B行的PK扫描:
限制(成本=0.58..4632.03 行=1 宽度=28)
-> 在 mcqueen_base_imagemeta2 上使用 mcqueen_base_imagemeta2_pkey 向后扫描索引(成本=0.58..364597074.75 行=78722 宽度=28)
过滤器:(image_id = ANY ('{123, ...}'::bigint[]))
如果LIMIT增加到2,它会按预期工作:
限制(成本=7585.92..7585.93 行=2 宽度=28)
-> 排序(成本=7585.92..7782.73 行=78722 宽度=28)
排序键:id DESC
-> 在 mcqueen_base_imagemeta2 上使用 … postgresql performance index-tuning paging postgresql-9.6 query-performance
我有一个带有遗留查询的 Rails 应用程序,我想对其进行翻新。当前实现执行两个 SQL 查询:一个获取大量 ID,第二个查询使用这些 ID 并应用一些额外的连接和过滤器来获得所需的结果。
我试图用避免往返的单个查询替换它,但这样做会导致我的本地测试环境(这是完整生产数据集的副本)的性能大幅下降。新查询中似乎没有使用索引,导致全表扫描。我曾希望单个查询能够保持与原始代码相同的性能,理想情况下,由于不需要发送所有 ID,因此可以对其进行改进。
这是我实际问题的最小化版本。稍大一点的版本在讨论为什么10000个ID的列表中一个复杂的查询有更好的表现与多个热膨胀系数相比,相当于SQL选择它们?.
有一个查询需要大约 6.5 秒来计算 10000 多个 ID 的列表。您可以visible_projects在下面的“建议查询”部分中将其视为 CTE 。然后将这些 ID 输入到此查询中:
EXPLAIN (ANALYZE, BUFFERS)
WITH visible_projects AS NOT MATERIALIZED (
SELECT
id
FROM
"projects"
WHERE
"projects"."id" IN (
-- 10000+ IDs removed
)),
visible_tasks AS MATERIALIZED (
SELECT
tasks.id
FROM
tasks
WHERE
tasks.project_id IN (
SELECT
id
FROM
visible_projects))
SELECT
COUNT(1)
FROM
visible_tasks;
Run Code Online (Sandbox Code Playgroud)
查询计划(depesz)
Aggregate (cost=1309912.31..1309912.32 rows=1 width=8) (actual time=148.661..153.739 …Run Code Online (Sandbox Code Playgroud) postgresql performance query-performance postgresql-performance
考虑以下示例:
CREATE TABLE test (
id SERIAL,
some_integer INT
);
INSERT INTO test (some_integer)
SELECT FLOOR(RANDOM()*100000) from generate_series(1,100000) s(i);
CREATE INDEX some_integer_idx ON test (some_integer);
EXPLAIN ANALYZE SELECT COUNT(DISTINCT some_integer) from test;
Run Code Online (Sandbox Code Playgroud)
它返回以下查询计划:
CREATE TABLE test (
id SERIAL,
some_integer INT
);
INSERT INTO test (some_integer)
SELECT FLOOR(RANDOM()*100000) from generate_series(1,100000) s(i);
CREATE INDEX some_integer_idx ON test (some_integer);
EXPLAIN ANALYZE SELECT COUNT(DISTINCT some_integer) from test;
Run Code Online (Sandbox Code Playgroud)
我很惊讶它仍然在测试中进行顺序扫描。简单地计算索引中的行数不是更快吗?
我试图尽可能详细地说明这一点。抱歉长度!
protein_snp_assoc我在 PostgreSQL(版本 12.13)数据库上创建了以下分区表:
CREATE TABLE protein_snp_assoc (
protein_id int not null,
snp_id int not null,
beta double precision,
se double precision,
logp double precision
) PARTITION BY RANGE (snp_id);
Run Code Online (Sandbox Code Playgroud)
然后,我根据以下模板创建了 51 个分区,每个分区包含大约 1.5 亿行(总共 76.5 亿行):
CREATE TABLE IF NOT EXISTS protein_snp_assoc_(x) PARTITION OF protein_snp_assoc
FOR VALUES FROM (y) TO (z);
Run Code Online (Sandbox Code Playgroud)
其中x范围从 1 到 51,并y, z定义间隔,每个长度为 150,000。例如,前两个和最后一个分区是:
protein_snp_assoc_1 FOR VALUES FROM (1) TO (150001),
protein_snp_assoc_2 FOR VALUES FROM (150001) TO (300001), ...
protein_snp_assoc_51 …Run Code Online (Sandbox Code Playgroud) postgresql database-design read-only-database query-performance postgresql-performance
postgresql ×10
performance ×5
index ×3
index-tuning ×3
aggregate ×1
count ×1
distinct ×1
paging ×1
partitioning ×1
string ×1