Postgresql 如何让Postgres在订购后计算列?
我有一些大型sql查询,在SELECT块中有许多计算列。此外,还可以按其中一个计算列进行排序,并且仅限100行。但是postgres计算每一行的所有列,而不仅仅是100行 让我举例说明 让我们创建一些测试表:Postgresql 如何让Postgres在订购后计算列?,postgresql,query-optimization,Postgresql,Query Optimization,我有一些大型sql查询,在SELECT块中有许多计算列。此外,还可以按其中一个计算列进行排序,并且仅限100行。但是postgres计算每一行的所有列,而不仅仅是100行 让我举例说明 让我们创建一些测试表: CREATE TABLE test_main(col1 INTEGER); 并用一些随机数据填充: DO $do$ BEGIN FOR r IN 1..100000 LOOP INSERT INTO test_main(col1) VALUES (trunc(random()
CREATE TABLE test_main(col1 INTEGER);
并用一些随机数据填充:
DO
$do$
BEGIN
FOR r IN 1..100000 LOOP
INSERT INTO test_main(col1) VALUES (trunc(random()*1000));
END LOOP;
END
$do$;
然后创建一些附加表:
CREATE TABLE test_main_agg1(
col1 INTEGER,
val INTEGER
);
CREATE TABLE test_main_agg2(
col1 INTEGER,
val INTEGER
);
并将其填满:
DO
$do$
DECLARE
r test_main%rowtype;
BEGIN
FOR r IN SELECT * FROM test_main LOOP
FOR i IN 1..5 LOOP
INSERT INTO test_main_agg1(col1, val) VALUES (r.col1, trunc(random()*1000));
INSERT INTO test_main_agg2(col1, val) VALUES (r.col1, trunc(random()*1000));
END LOOP;
END LOOP;
END
$do$;
当然,还要创建一些索引:
CREATE INDEX test_main_indx ON test_main(col1);
CREATE INDEX test_main_agg1_val_indx ON test_main_agg1(col1,val);
CREATE INDEX test_main_agg2_val_indx ON test_main_agg2(col1,val);
现在,如果我们执行此查询:
SELECT col1,
(SELECT MAX(val) FROM test_main_agg1 g WHERE g.col1=m.col1) max_val1,
(SELECT MAX(val) FROM test_main_agg2 g WHERE g.col1=m.col1) max_val2
FROM test_main m
LIMIT 100;
由于索引的原因,它将非常快。如果我们增加col1的订单,速度仍然会很快。但如果我们使用max_val1的ORDER,则需要大约2秒钟。
如果我们使用“ORDER BY max_val1”对查询运行解释分析,我们将看到以下行:
SubPlan 4
-> Result (cost=4.06..4.07 rows=1 width=0) (actual time=0.011..0.011 rows=1 loops=100000)
InitPlan 3 (returns $3)
-> Limit (cost=0.42..4.06 rows=1 width=4) (actual time=0.010..0.010 rows=1 loops=100000)
-> Index Only Scan Backward using test_main_agg2_val_indx on test_main_agg2 g_1 (cost=0.42..1818.25 rows=500 width=4) (actual time=0.010..0.010 rows=1 loops=100000)
Index Cond: ((col1 = m.col1) AND (val IS NOT NULL))
Heap Fetches: 100000
这意味着,postgres计算100000行的max_val2,而不仅仅是100行。我理解为什么postgres需要计算max_val1,而不是max_val2
可能有一些提示或类似的东西告诉postgres在执行排序和限制后计算列?限制整个查询的输出,而不是主查询中的子查询的输出。如果只希望最大值为100行,则需要首先选择它们,然后对该子集应用最大值:
SELECT col1,
(SELECT MAX(val) FROM test_main_agg1 g WHERE g.col1=m.col1) max_val1,
(SELECT MAX(val) FROM test_main_agg2 g WHERE g.col1=m.col1) max_val2
FROM (
select val, col1
from test_main
LIMIT 100
) m;
请注意,没有ORDER BY的限制实际上没有意义。关系数据库中的行没有顺序。因此,除非指定排序顺序,否则不存在表中的前100行 无关,但是:您的DO块可以替换为简单的INSERT语句:例如:INSERT into test_maincol1从generate_series 1100000中选择truncrandom*1000;谢谢,我不知道生成_系列函数。我会记住:是的,你是对的。我忘记了在子查询中使用ORDERBY和LIMIT的可能性。然后我可以将我的示例中的查询重写为:选择t.*,选择。。。最大值2从选择列1,选择。。。测试主订单的最大值为100 t;