我有一个基于日期字段和数字字段的订单查询 Postgres 中的表,该表有 1000000 条记录
表的数据类型为:
fcv_id = serial
fcv_fecha_comprobante = timestamp without time zone
fcv_numero_comprobante = varchar(60)
Run Code Online (Sandbox Code Playgroud)
查询是:
SELECT fcv_id, fcv_fecha_comprobante FROM factura_venta
ORDER BY fcv_fecha_comprobante, fcv_numero_comprobante
Run Code Online (Sandbox Code Playgroud)
这个查询大约需要 5 秒,但如果我取出“order by”,查询只需要 0.499 秒
我遇到的问题是我需要在尽可能短的时间内运行这个查询,所以我在谷歌上搜索我可以做什么并使用以下查询创建一个复合索引
CREATE INDEX factura_venta_orden ON factura_venta
USING btree (fcv_fecha_comprobante ASC NULLS LAST
, fcv_numero_comprobante ASC NULLS LAST);
ALTER TABLE factura_venta CLUSTER ON factura_venta_orden;
Run Code Online (Sandbox Code Playgroud)
但是查询花费的时间相同甚至更多。
我使用的是 Postgres 9.0.13,这里是 73436 行的 EXPLAIN
Sort (cost=11714.03..11897.62 rows=73436 width=27) (actual time=1260.759..1579.853 rows=73436 loops=1)
Sort Key: fcv_fecha_comprobante, fcv_numero_comprobante
Sort Method: external merge …Run Code Online (Sandbox Code Playgroud) 这个问题与我之前问过的问题有关:PostgreSQL 中复合索引中的列顺序(和查询顺序)
我想我可以在这里尖锐和限制我的问题,而不是超载这个问题。鉴于以下查询(和 EXPLAIN ANALYZE),我正在创建的复合索引有帮助吗?
第一个查询仅使用简单索引(大纲上的 GIST)和(pid 上的 BTREE)运行。
查询是:
EXPLAIN ANALYZE SELECT DISTINCT ON (path) oid, pid, product_name, type, path, size
FROM portal.inventory AS inv
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.51947021484375 51.55059814453125, 18.9129638671875 51.55059814453125, 18.9129638671875 48.8287353515625, 21.51947021484375 48.8287353515625, 21.51947021484375 51.55059814453125))'), inv.outline)
AND (inv.pid in (20010,20046))
Run Code Online (Sandbox Code Playgroud)
——
结果如下(速度更快,但也许这只是因为数据库是热的)。
"Unique (cost=581.76..581.76 rows=1 width=89) (actual time=110.436..110.655 rows=249 loops=1)"
" -> Sort (cost=581.76..581.76 rows=1 width=89) (actual time=110.434..110.477 rows=1377 loops=1)"
" Sort Key: path"
" Sort Method: quicksort Memory: 242kB"
" -> Bitmap Heap Scan on inventory …Run Code Online (Sandbox Code Playgroud) 我的系统中有一个非常重要的查询,由于表上的数据量很大,执行时间太长。我是一名初级 DBA,我需要为此进行最佳优化。每个表大约有 8000 万行。
表是:
tb_pd:
Column | Type | Modifiers | Storage | Stats target | Description
---------------------+---------+-----------+---------+--------------+-------------
pd_id | integer | not null | plain | |
st_id | integer | | plain | |
status_id | integer | | plain | |
next_execution_date | bigint | | plain | |
priority | integer | | plain | |
is_active | integer | | plain | |
Indexes:
"pk_pd" PRIMARY KEY, btree (pd_id)
"idx_pd_order" btree (priority, next_execution_date) …Run Code Online (Sandbox Code Playgroud) 我有一个包含三个整数列id和a的表b。
我想获取所有记录,其中a或b匹配指定参数排序id:
select id, a, b from t where a=x or b=x order by id
Run Code Online (Sandbox Code Playgroud)
请注意,和 的x值相同。ab
这里最合适的索引是什么?
更新:我们总是在列和中寻找相同的值,这一事实有什么用处吗?我们可以为此创建一个表达式索引吗?ab
我有这种 N:M 关系:
CREATE TABLE auth_user (
id integer NOT NULL PRIMARY KEY,
username character varying(150) NOT NULL UNIQUE
);
CREATE TABLE auth_group (
id integer NOT NULL PRIMARY KEY,
name character varying(80) NOT NULL UNIQUE
);
CREATE TABLE auth_user_groups (
id integer NOT NULL PRIMARY KEY,
user_id integer REFERENCES auth_user(id) NOT NULL,
group_id integer REFERENCES auth_group(id) NOT NULL,
CONSTRAINT user_groups UNIQUE(user_id, group_id)
);
INSERT INTO auth_user VALUES (1, 'user1');
INSERT INTO auth_user VALUES (2, 'user2');
INSERT INTO auth_group VALUES …Run Code Online (Sandbox Code Playgroud) 我有一个包含大约 1000 万行的表,其中包含一个主键和一个定义在其上的索引:
create table test.test_table(
date_info date not null,
string_data varchar(64) not null,
data bigint
primary key(date_info, string_data));
create index test_table_idx
on test.test_table(string_data);
Run Code Online (Sandbox Code Playgroud)
我有一个使用了的查询test_table_idx:
select distinct date_info from test.test_table where string_data = 'some_val';
Run Code Online (Sandbox Code Playgroud)
问题是第一次运行查询最多可能需要 20 秒,而在任何后续运行中都需要 < 2 秒。
有没有办法将整个索引加载到内存中,而不是在第一次访问时获取数据库加载信息?
假设您有一张桌子groups和一张桌子item。每个项目都属于一个组。它是该群体的固有组成部分。一个项目不能存在于一个组之外,也不能移动到另一个组中。
当试图决定item表的主键时,我应该使用什么?
我应该像这样组成一个人工全局序列键:
CREATE TABLE items
(
item serial PRIMARY KEY,
group integer NOT NULL REFERENCES groups(group),
);
Run Code Online (Sandbox Code Playgroud)
...或者我应该使用复合键和每组项目序列,如下所示:
CREATE TABLE items
(
group integer NOT NULL REFERENCES groups(group),
item integer NOT NULL,
PRIMARY KEY(group, item)
);
Run Code Online (Sandbox Code Playgroud)
我更倾向于第二种解决方案的原因是帖子 URL 将始终显示组和项目,因此将它们都作为复合主键是有意义的。在第一种解决方案的情况下,URL 包含多余的信息,因为组 ID 已经可以单独从项目 ID 中推导出来。但是,URL 结构是给定的,不能更改。
第二种解决方案的缺点是您必须管理每个组的序列(即每个组的每个项目整数应从 0 开始)。
在最佳实践、规范化和性能方面哪个更好?或者这只是品味问题?
我有一个表,用于表上的多对多关系users来表示用户之间的跟随关系:
CREATE TABLE users (
id text PRIMARY KEY,
username text NOT NULL
);
CREATE TABLE followers (
userid text,
followid text,
PRIMARY KEY (userid, followid),
CONSTRAINT followers_userid_fk FOREIGN KEY (userid) REFERENCES users (id),
CONSTRAINT followers_followid_fk FOREIGN KEY (followid) REFERENCES users (id)
);
CREATE INDEX followers_followid_idx ON followers (followid);
Run Code Online (Sandbox Code Playgroud)
当我想使用与用户相关的数据创建 JSON 响应时,我有两种情况:
用户数据对象应包含两个用户 ID 数组,一个是他们关注的用户,另一个是关注他们的用户。为了创建这两个字段,我使用了以下SELECT语句。
DECLARE follows RECORD;
SELECT array (select followid FROM followers where userid = Puserid) AS following, …Run Code Online (Sandbox Code Playgroud) 我有一个包含超过 10.000.000 条记录的表,并且我正在创建一个返回大约 4436 条记录的查询。
碰巧它给我的印象是获取最后一条记录的查询成本非常高。
Index Scan using idx_name on task (cost=0.28..142102.57 rows=3470 width=34) (actual time=14.690..22.894 rows=4436 loops=1)
" Index Cond: ((situation = ANY ('{0,1,2,3,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}'::integer[])) AND (deadline < CURRENT_TIMESTAMP))"
Planning Time: 1.335 ms
JIT:
Functions: 5
Options: Inlining false, Optimization false, Expressions true, Deforming true
Timing: Generation 1.654 ms, Inlining 0.000 ms, Optimization 1.214 ms, Emission 13.163 ms, Total 16.030 ms
Execution Time: 24.758 ms
Run Code Online (Sandbox Code Playgroud)
这个成本水平是否可以接受,或者这个指标是否需要改进?
指数:
CREATE INDEX idx_name ON task (situation, deadline, approved)
WHERE
deadline IS NOT …Run Code Online (Sandbox Code Playgroud) 我正在管理一个包含几百万条记录的表,这些记录被实时插入。我的应用程序的一部分需要显示最后插入的 N 行,所以一开始我只是查询:
select id, logdate, content from measurements order by logdate DESC limit 500;
Run Code Online (Sandbox Code Playgroud)
几天后,我发现设置id为(对于此示例)更快10000000000 - extract(epoch from logdate),并将其用作PRIMARY KEY,所以
select id, date, content from measurements limit 500;
Run Code Online (Sandbox Code Playgroud)
自然会按 排序id,因此会产生最新的记录。
随着表的增长,它变得难以管理,所以我求助于分区。我按照文档说的那样做了:
CREATE TABLE measurement_y2007m11 (
CHECK ( logdate >= DATE '2007-11-01' AND logdate < DATE '2007-12-01' )
) INHERITS (measurement);
CREATE TABLE measurement_y2007m12 (
CHECK ( logdate >= DATE '2007-12-01' AND logdate < DATE '2008-01-01' )
) INHERITS (measurement); …Run Code Online (Sandbox Code Playgroud) postgresql ×10
index ×5
performance ×3
index-tuning ×2
many-to-many ×2
cache ×1
join ×1
optimization ×1
partitioning ×1
primary-key ×1
view ×1