【问题标题】:postgresql - are my indexes or column types slowing down my query?postgresql - 我的索引或列类型是否会减慢我的查询速度?
【发布时间】:2015-09-12 16:56:24
【问题描述】:

我有一个我在本地创建的表,用于在大约 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

【问题讨论】:

  • 当表中有 customerid 时,为什么要使用 customername 作为分区键?
  • @DanielVérité - 现在减少到 198 秒 :-)
  • 有多少不同的客户?
  • @wildplasser - 330 万
  • 在这种情况下,将客户规范化到一个单独的表中将无济于事(很多)唯一可能有帮助的就是(customerid,orderdate)上的复合索引

标签: postgresql postgresql-performance


【解决方案1】:

覆盖指数

customerid 分区,如@Daniel commentedinteger 更小,排序更便宜。如果结果中不需要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;

【讨论】:

  • 感谢物化视图的提示!打算尝试一下并报告。
猜你喜欢
  • 2022-09-30
  • 2016-08-28
  • 2017-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-07
相关资源
最近更新 更多