我有一个我在本地创建的表,在一个有大约400万行(最初是文本文件)的数据集上使用PG的一些窗口函数。每行对应一个客户订单。
CREATE TABLE orders
(
orderid integer,
customerid integer,
orderdate date,
status text,
amount money,
tax money,
customername text,
customerstate text
我在i7 8gb RAM Windows 8机器上本地运行数据库。我在orderid,customerid和orderdate上有btree索引(索引?)。
当我运行以下查询时,需要300秒(appx)。我希望有一些基本的调整,我可以把它缩短到一分钟,但我不是DBA。有人有提示吗?
select orderid, customername, orderdate,
rank() OVER (PARTITION BY customername ORDER BY orderdate ASC) as cust_ord_nbr
from orders
答案 0 :(得分:1)
customerid
分区,如@Daniel commented。 integer
更小,更便宜。如果您在结果中不需要customername
,请将其完全替换为customerid
。
多列索引可以提供帮助(例如@wildplasser commented)。如果它是(大多数)只读表,那么"覆盖"允许仅索引扫描的索引会更快 - 特别是如果包含的列很小:
CREATE INDEX orders_nbr_idx ON orders (customerid, orderdate, orderid);
只有从中获取索引扫描才能将orderid
添加到索引中。如果您需要customername
,请同时添加。更多:
如果它(大部分)是只读表,请执行一次昂贵的查询并将快照保存为MATERIALIZED VIEW
以便重复使用...
你可以做一些小事来减少内存占用。在playing column tetris之后,这将节省当前丢失到填充的每行0-7个字节:
CREATE TABLE orders (
orderid integer,
customerid integer,
amount money,
tax money,
orderdate date,
status text,
customername text,
customerstate text
);
如果将结果写入另一个表(或MATERIALIZED VIEW
),它将节省一些以类似方式优化查询。 rank()
生成bigint
,通过强制转换为int
每行节省8个字节(4 + 4填充):
SELECT orderid, customername, orderdate
-- orderid, customerid, orderdate -- good enough?
, rank() OVER (PARTITION BY customerid
ORDER BY orderdate)::int AS cust_ord_nbr
FROM orders;