CodeGym /Courses /SQL SELF /Optimizing Functions for Working with Large Amounts of Da...

Optimizing Functions for Working with Large Amounts of Data

SQL SELF
Level 56 , Lesson 2
Available

When we talk about optimizing functions in PostgreSQL, we usually mean two key things: indexing and partitioning. These two techniques help you handle large amounts of data faster by cutting out unnecessary calculations and letting you hit the data "right on target." Let's break it down in detail.

Indexes in the database world work just like indexes in books. When you look for info in a book, you don't read every page in order. You open the index, find the topic you want, and jump straight to the right page. Indexes in PostgreSQL do pretty much the same thing.

Creating Indexes

You create indexes using the CREATE INDEX command. Here's a simple example:

-- Creating an index on the id column of the users table to speed up search
CREATE INDEX idx_users_id ON users (id);

Now, if you run a query like:

SELECT * FROM users WHERE id = 42;

PostgreSQL will use the created index to quickly find the row you need.

Example: Optimizing a Function Using Indexes

Let's say we have a function that selects order data from the orders table by user:

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

If the orders table has millions of rows, running this function will be slow. The fix? Create an index on user_id:

CREATE INDEX idx_orders_user_id ON orders (user_id);

Now the query inside the function will be way faster, since PostgreSQL will use the index to look up rows.

Types of Indexes

PostgreSQL supports a bunch of index types, but the most popular are B-TREE and GIN. Here's a quick comparison:

Index Type Usage Example
B-TREE Standard index for searching. Searching by numbers, strings (=, >, <).
GIN For full-text search or working with JSON. Searching by arrays, JSONB.

If you want to dig deeper into indexes, check out the official PostgreSQL docs.

Data Partitioning

If indexes are about speeding up search, partitioning is a method that helps you split a table into smaller "chunks" (partitions). This is super useful when you have a massive amount of data in one table.

Imagine you have an orders table that stores orders for the last 10 years. If you run a query to find orders from the last month, PostgreSQL will still scan the whole table, which is expensive. Partitioning solves this by splitting the data, for example, by year.

Creating a Partitioned Table

Here's how you can create a partitioned table:

-- Create the orders table as a parent partition
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    order_date DATE NOT NULL,
    user_id INT NOT NULL
) PARTITION BY RANGE (order_date);

-- Create child tables for each year
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');

Now, when you run a query like:

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

PostgreSQL will instantly figure out it only needs to search in the orders_2023 table, instead of scanning the whole thing.

Using Partitioning in Functions

Imagine we have a function that selects orders for a specific year. Thanks to partitioning, the queries inside the function will be faster, since PostgreSQL will work with the specific child table.

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;

Practical Cases

  1. Indexing Cases

Searching by strings: if you have a table with products and you often search for products by name, create an index on the name field:

CREATE INDEX idx_products_name ON products (name);

Speeding up sorting: if your queries often sort by date, create an index:

CREATE INDEX idx_orders_date ON orders (order_date);
  1. Partitioning Cases

Historical data: if your table has data with a timestamp, partitioning by days, months, or years will make queries a lot faster.

Geographic data: if your table has data by country, create partitions for each country.

Potential Mistakes and How to Fix Them

A lot of devs make the mistake of creating too many indexes. This actually slows down inserts and updates, since PostgreSQL has to update the indexes every time the table changes. Tip: only create indexes on fields you often use in WHERE conditions or sorting.

Another common mistake is bad partitioning. If you create too many tiny partitions (like by day instead of by month), it can lead to overhead managing all those tables.

2
Task
SQL SELF, level 56, lesson 2
Locked
Creating an index to speed up search
Creating an index to speed up search
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION