我有一个由Django的ORM生成的查询,这需要花费数小时才能运行.
该report_rank表(5000万行)与report_profile(100k行)的一对多关系.我正在尝试检索report_rank每个的最新版本report_profile.
我在一个额外的大型Amazon EC2服务器上运行Postgres 9.1,它有足够的可用内存(使用2GB/15GB).磁盘IO当然非常糟糕.
我有索引report_rank.created以及所有外键字段.
我该怎么做才能加快查询速度?我很乐意尝试使用查询的不同方法,如果它将是高性能的,或者调整所需的任何数据库配置参数.
EXPLAIN
SELECT "report_rank"."id", "report_rank"."keyword_id", "report_rank"."site_id"
, "report_rank"."rank", "report_rank"."url", "report_rank"."competition"
, "report_rank"."source", "report_rank"."country", "report_rank"."created"
, MAX(T7."created") AS "max"
FROM "report_rank"
LEFT OUTER JOIN "report_site"
ON ("report_rank"."site_id" = "report_site"."id")
INNER JOIN "report_profile"
ON ("report_site"."id" = "report_profile"."site_id")
INNER JOIN "crm_client"
ON ("report_profile"."client_id" = "crm_client"."id")
INNER JOIN "auth_user"
ON ("crm_client"."user_id" = "auth_user"."id")
LEFT OUTER JOIN "report_rank" T7
ON ("report_site"."id" = T7."site_id")
WHERE ("auth_user"."is_active" = True AND "crm_client"."is_deleted" …Run Code Online (Sandbox Code Playgroud) 我有以下查询,它为每个查询获取id最新的N :observationsstation
SELECT id
FROM (
SELECT station_id, id, created_at,
row_number() OVER(PARTITION BY station_id
ORDER BY created_at DESC) AS rn
FROM (
SELECT station_id, id, created_at
FROM observations
) s
) s
WHERE rn <= #{n}
ORDER BY station_id, created_at DESC;
Run Code Online (Sandbox Code Playgroud)
我有指标的id,station_id,created_at。
这是我想出的唯一解决方案,每个站可以获取多个记录。但是,它非常慢(81000条记录的表为154.0毫秒)。
如何加快查询速度?
这是plpgsql 函数的一个变体,它返回多个列,并被多次调用。然而,我希望找到针对我的特殊情况的解决方案。
我有一个函数,它处理具有给定参数的行数组,并返回一组行+一个新列。
CREATE OR REPLACE foo(data data[], parameter int) RETURNS SETOF enhanceddata AS
...
Run Code Online (Sandbox Code Playgroud)
该函数适用于只有一组数据的测试用例
SELECT * FROM foo( (SELECT ARRAY_AGG(data) FROM datatable GROUP BY dataid WHERE dataid = something), 1)
Run Code Online (Sandbox Code Playgroud)
但我想让它处理多组数据,而不将 a 传递dataid给函数。我尝试了多种变体:
SELECT dataid, (foo(ARRAY_AGG(data)),1).*
FROM dataset
WHERE dataid = something -- only testing on 1
GROUP BY dataid
Run Code Online (Sandbox Code Playgroud)
但该函数会为每一列调用一次。
我有一个users包含字段id和 的表email。id是主键并且email也被索引。
database> \d users
+-----------------------------+-----------------------------+-----------------------------------------------------+
| Column | Type | Modifiers |
|-----------------------------+-----------------------------+-----------------------------------------------------|
| id | integer | not null default nextval('users_id_seq'::regclass) |
| email | character varying | |
+-----------------------------+-----------------------------+-----------------------------------------------------+
Indexes:
"users_pkey" PRIMARY KEY, btree (id)
"index_users_on_email" UNIQUE, btree (email)
Run Code Online (Sandbox Code Playgroud)
如果我在子查询中使用子句查询表,distinct on (email)我会得到显着的性能损失。
database> \d users
+-----------------------------+-----------------------------+-----------------------------------------------------+
| Column | Type | Modifiers |
|-----------------------------+-----------------------------+-----------------------------------------------------|
| id | integer | not null default nextval('users_id_seq'::regclass) |
| …Run Code Online (Sandbox Code Playgroud) postgresql performance greatest-n-per-group distinct-on postgresql-performance
SELECT DISTINCT options.id, options.foo_option_id, options.description
FROM vehicles
INNER JOIN vehicle_options ON vehicle_options.vehicle_id = vehicles.id
INNER JOIN options ON options.id = vehicle_options.option_id
INNER JOIN discounted_vehicles ON vehicles.id = discounted_vehicles.vehicle_id
WHERE discounted_vehicles.discount_id = 4;
Run Code Online (Sandbox Code Playgroud)
上面的查询返回 2067 行,它在 1.7 秒内在本地运行。我想知道它是否尽可能快,或者我是否可以以某种方式进一步调整它,因为这个数据集会随着时间的推移而快速增长。
我在速度不变的情况下尝试过的事情:
1 - 更改连接顺序,从最小的表连接到最大的表。
2 - 向discounted_vehicles.discount_id 添加索引。