PostgreSQL
  • Introduction
  • PostgreSQL
    • Введение
    • Установка и базовые операции
    • Запуск команд SQL из файла
    • Агрегатные функции
    • Реляционная алгебра
    • Создание счётчика
    • Изменение структуры таблицы
    • Диапазоны и множества
    • Регулярные выражения
    • Скрипты SQL
    • Группировка
    • Регистры строк
    • Уникальные поля
    • Сортировки и вычисляемые поля
    • Представления
    • Массивы и триггеры
    • Индексы и анализ
    • Текстовый анализ
    • Использование RETURNING
    • Возврат массива записей
    • Внешние ключи
    • Ускорение БД
    • Запросы WITH
    • JSON
Powered by GitBook
On this page
  • Поиск строк без использования индексов
  • Использование btree индексов для поиска и сортировки строк
  • Удаление индексов
  • Функциональный индекс
  • Использование функционального индекса с собственными функциями

Was this helpful?

  1. PostgreSQL

Индексы и анализ

Создадим таблицу для хранения двух текстовых строк.

CREATE TABLE t (t1 BIGSERIAL PRIMARY KEY, t2 TEXT, t3 TEXT);

Напишем функцию для получения случайного целого числа.

CREATE OR REPLACE FUNCTION get_random() RETURNS INTEGER AS $$
    DECLARE answer INTEGER;
BEGIN
    answer = CAST(floor( random() * 100000 ) AS INTEGER) % 10 + 2;   
    RETURN answer;
END;

$$ LANGUAGE plpgsql;

Напишем функцию для получения случайной текстовой строки.

CREATE OR REPLACE FUNCTION get_string() RETURNS TEXT AS $$
    DECLARE my_array TEXT ARRAY;
    DECLARE string_length INTEGER;
    DECLARE answer TEXT;
BEGIN
    my_array = ARRAY ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'y', 'z', 'q', 'q', 'q', 'q', 'q'];
    string_length = get_random() * 2;
    answer = '';
    FOR I IN 1..string_length LOOP
        answer = answer || my_array[get_random()];
    END LOOP;
    RETURN answer;
END;

$$ LANGUAGE plpgsql;

Напишем функцию, которая добавляет определённое количество записей в таблицу.

CREATE OR REPLACE FUNCTION add_random_records (records_number INTEGER) RETURNS INTEGER AS $$
    DECLARE iter INTEGER;
    DECLARE s2 TEXT;
    DECLARE s3 TEXT;
BEGIN
    FOR iter IN 1..records_number LOOP
        s2 = get_string();
        s3 = get_string();
        INSERT INTO t (t2, t3) VALUES (s2, s3);
    END LOOP;
    RETURN records_number;
END;

$$ LANGUAGE plpgsql;

По умолчанию создаётся один индекс для ключевого поля счётчика.

Поиск строк без использования индексов

Для заполнения таблицы данными вызываем процедуру.

SELECT add_random_records (200000);

Проанализируем запрос на выборку записи, где поле t2 имеет определённое значение.

EXPLAIN ANALYZE SELECT * FROM t WHERE t2 = 'ddfgfqfbgdyefzgcef';

Проанализируем запрос на выборку, где поля t2 и t3 имеют определённые значения.

EXPLAIN ANALYZE SELECT * FROM t WHERE t2 = 'ddfgfqfbgdyefzgcef' AND t3 = 'eyeaezdgya';

Использование btree индексов для поиска и сортировки строк

Удаляем таблицу.

DROP TABLE t;

Создаём таблицу заново.

CREATE TABLE t (t1 BIGSERIAL PRIMARY KEY, t2 TEXT, t3 TEXT);

Создаём два btree индекса.

CREATE INDEX my_t2_index ON t USING btree (t2);
CREATE INDEX my_t3_index ON t USING btree (t3);

Заполняем пустую таблицу данными.

SELECT add_random_records (200000);

Проанализируем запрос на выборку, где поле t2 имеет определённое значение.

EXPLAIN ANALYZE SELECT * FROM t WHERE t2 = 'dcyyqqyzgbbadbzgag';

Проанализируем запрос на выборку, где поля t2 и t3 имеют определённые значения.

EXPLAIN ANALYZE SELECT * FROM t WHERE t2 = 'dcyyqqyzgbbadbzgag' AND t3 = 'cazaecyf';

Проанализируем запрос на вывод первых десяти записей после сортировки по полю t2.

EXPLAIN ANALYZE SELECT * FROM t ORDER BY t2 ASC LIMIT 10;

В результате анализа выясняется, что поиск и сортировка данных с использованием индексов работает гораздо быстрее.

Удаление индексов

Удаляем созданные индексы

DROP INDEX IF EXISTS my_t2_index;
DROP INDEX IF EXISTS my_t3_index;

Функциональный индекс

Создадим таблицу для хранения строк.

CREATE TABLE s (s1 SERIAL PRIMARY KEY, s2 TEXT);

Создадим функциональный индекс для поля s2.

Индекс использует функцию перевода строки в нижний регистр.

CREATE INDEX my_s2_func_index ON s ( LOWER(s2) );

Заполним таблицу строками, содержащими большие и маленькие буквы.

Выполним запрос, который ищет запись с определённым значением поля s2 без использования функции LOWER.

Данный запрос будет работать медленно, так как он будет перебирать все строки таблицы.

EXPLAIN ANALYZE SELECT * FROM s WHERE s2 = 'FZgyqdYfEDcFfzEAGC';

Теперь выполним запрос, который ищет запись по полю s2 c использованием функции LOWER.

Данный запрос будет работать быстро, так как он использует функциональный индекс.

EXPLAIN ANALYZE SELECT * FROM s WHERE LOWER(s2) = LOWER('FZgyqdYfEDcFfzEAGC');

Использование функционального индекса с собственными функциями

Напишем собственную функцию, возвращающую длину строки.

Слово IMMUTABLE было добавлено, чтобы было можно использовать данную функцию для индекса.

CREATE OR REPLACE FUNCTION get_number (q TEXT) RETURNS INTEGER AS $$
    DECLARE n INTEGER;
BEGIN
    n = LENGTH(q);
    RETURN n;
END;

$$ LANGUAGE plpgsql IMMUTABLE;

Создадим таблицу для хранения строк.

CREATE TABLE x (x1 SERIAL PRIMARY KEY, x2 TEXT);

Создадим функциональный индекс для поля x2.

Индекс использует функцию get_number.

CREATE INDEX my_func_ind_x2_x2 ON x ( get_number(x2) );

Заполним таблицу записями.

Напишем запрос на получение записей, у которых длина строки в поле x2 равняется восьми.

Данный запрос будет работать быстро, так как используется функциональный индекс.

EXPLAIN ANALYZE SELECT * FROM x WHERE get_number(x2) = 8;
PreviousМассивы и триггерыNextТекстовый анализ

Last updated 5 years ago

Was this helpful?