CodeGym /课程 /SQL SELF /针对大数据量的函数优化

针对大数据量的函数优化

SQL SELF
第 56 级 , 课程 2
可用

说到在PostgreSQL里优化函数,通常主要有两个核心点:索引分区。这两招能让你处理大数据时更快,少做无用功,查数据也能“直奔主题”。下面咱们详细聊聊。

数据库里的索引其实就像书的目录。你找内容时不会一页页翻,而是看目录,找到主题直接跳页。PostgreSQL里的索引也是这么干的。

创建索引

索引用CREATE INDEX命令建。举个简单例子:

-- 在users表的id列上建索引,加速查找
CREATE INDEX idx_users_id ON users (id);

现在,如果你执行类似这样的查询:

SELECT * FROM users WHERE id = 42;

PostgreSQL会用你刚建的索引,飞快地找到那一行。

例子:用索引优化函数

假设我们有个函数,要从orders表里查某个用户的订单:

CREATE OR REPLACE FUNCTION get_user_orders(user_id INT)
RETURNS TABLE(order_id INT, order_date DATE) AS $$
BEGIN
    RETURN QUERY 
    SELECT id, order_date 
    FROM orders 
    WHERE user_id = user_id;
END; 
$$ LANGUAGE plpgsql;

如果orders表有几百万行,这函数跑起来会很慢。咋办?在user_id上建个索引:

CREATE INDEX idx_orders_user_id ON orders (user_id);

这样函数里的查询就会快很多,因为PostgreSQL会用索引来找行。

索引的类型

PostgreSQL支持好几种索引,最常用的是B-TREEGIN。简单对比如下:

索引类型 用途 例子
B-TREE 标准查找用的索引。 查数字、字符串(=, >, <)。
GIN 全文检索或JSON用。 查数组、JSONB。

想深入了解索引,可以看看PostgreSQL官方文档

数据分区

索引是查找加速器,分区则是把大表拆成小块(分区)。当你一张表里有巨量数据时,这招特别有用。

比如你有个orders表,存了10年订单。如果你查最近一个月的订单,PostgreSQL默认还是会扫全表,挺费劲。分区能解决这问题,比如按年拆分。

创建分区表

你可以这样建分区表:

-- 创建orders表为父分区表
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    order_date DATE NOT NULL,
    user_id INT NOT NULL
) PARTITION BY RANGE (order_date);

-- 为每年建子表
CREATE TABLE orders_2023 PARTITION OF orders FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
CREATE TABLE orders_2022 PARTITION OF orders FOR VALUES FROM ('2022-01-01') TO ('2023-01-01');

现在你查类似这样的数据:

SELECT * FROM orders WHERE order_date >= '2023-01-01' AND order_date < '2023-02-01';

PostgreSQL会立刻知道只用查orders_2023,不用全表遍历。

在函数里用分区

假如我们有个函数,要查某一年的订单。因为用了分区,函数里的查询会快很多,因为PostgreSQL只查对应的子表。

CREATE OR REPLACE FUNCTION get_orders_by_year(year INT)
RETURNS TABLE(order_id INT, order_date DATE) AS $$
BEGIN
    RETURN QUERY 
    SELECT id, order_date 
    FROM orders 
    WHERE order_date >= make_date(year, 1, 1) 
      AND order_date < make_date(year + 1, 1, 1);
END;
$$ LANGUAGE plpgsql;

实战案例

  1. 索引案例

按字符串查找:比如你有个商品表,经常按名字查商品,就在name字段上建索引:

CREATE INDEX idx_products_name ON products (name);

加速排序:如果经常按日期排序查询,也建个索引:

CREATE INDEX idx_orders_date ON orders (order_date);
  1. 分区案例

历史数据:如果表里有时间戳,按天、月或年分区能大大加快查询。

地理数据:如果表里有国家字段,可以按国家分区。

常见坑和解决办法

很多开发者会犯一个错,就是建太多索引。这样会导致插入和更新变慢,因为每次表变了,PostgreSQL都得更新索引。建议:只在你经常用来查条件或排序的字段上建索引。

还有一个常见坑是分区分得太细,比如按天分而不是按月,这样会让表管理变得很麻烦,性能反而不好。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION