indexation et optimisation postgresql

Introduction à l'indexation

L'index (Index) peut être utilisé pour améliorer les performances des requêtes de la base de données ; cependant, l'index nécessite également la lecture et l'écriture, et il prend également plus d'
espace de stockage ; par conséquent, la compréhension et l'utilisation appropriée des index sont cruciales pour l'optimisation de la base de données. Dans cet article, nous expliquerons comment
utiliser efficacement les index PostgreSQL.

-- 创建表
CREATE TABLE test (
 id integer,
 name text
);
-- generate_series 产生序列
INSERT INTO test
SELECT v,'val:'||v FROM generate_series(1, 10000000) v;
SELECT name FROM test WHERE id = 10000;

Sans index, la base de données devrait analyser la table entière pour trouver les données correspondantes. Vous pouvez utiliser la commande EXPLAIN pour voir
le plan d'exécution de la base de données, qui correspond aux étapes spécifiques permettant à PostgreSQL d'exécuter des instructions SQL
.

-- Parallel Seq Scan 表示并行顺序扫描,执行消耗了大量时间
--;由于表中有包含大量数据,而查询只返回一行数据,显然这种方法效率很低。
explain analyze
SELECT name FROM test WHERE id = 10000;

Insérer la description de l'image ici

--如果在 id 列上存在索引,则可以通过索引快速找到匹配的结果。我们先创建一个索引:
CREATE INDEX test_id_index ON test (id);
-- 创建索引之后,再次查看数据库的执行计划
explain analyze
SELECT name FROM test WHERE id = 10000;

Insérer la description de l'image ici
Index Scan représente une analyse d'index, et l'exécution consomme 1,3 ms ; cette méthode est similaire à l'index de mots-clés à la fin du livre.
Les lecteurs parcourir l'index relativement rapidement et passer à la page appropriée sans avoir à lire le livre en entier pour y accéder. trouver la page intéressante .

Les index peuvent non seulement optimiser les instructions de requête, mais certaines instructions UPDATE et DELETE contenant des conditions WHERE peuvent également
utiliser des index pour améliorer les performances, car la condition préalable à la modification des données est de trouver les données.

De plus, les index peuvent également être utilisés pour optimiser les requêtes de jointure. La création d'index basés sur des champs dans des conditions de jointure peut améliorer les
performances des requêtes de jointure. Les index peuvent même optimiser les opérations de regroupement ou de tri car l'index lui-même est organisé et stocké de manière séquentielle.

D'un autre côté, le système nécessite un certain prix pour maintenir l'indice, augmentant ainsi la charge des opérations de modification des données. Par conséquent, nous
devons créer des index de manière raisonnable et, en général, créer uniquement des index pour les champs fréquemment utilisés. Tout comme pour un livre, il est impossible
de créer un index pour chaque mot-clé du livre.

Type d'index

PostgreSQL prend en charge plusieurs types d'index : index B-tree, hash, GiST, SP-GiST, GIN et BRIN. Chaque
index est basé sur une structure de stockage et un algorithme différents et est utilisé pour optimiser différents types de requêtes. Par défaut, PostgreSQL crée
des index B-tree car il convient à la plupart des requêtes

Index de l'arbre B


B-tree est un arbre auto-équilibré qui stocke les données en séquence et prend en charge la recherche, l'insertion, la suppression et l'accès séquentiel avec une complexité temporelle logarithmique (O(logN)) .
L'optimiseur PostgreSQL prend en compte les index B-tree pour les opérateurs de comparaison suivants sur les colonnes d'index :
• <
• <=
• =
• >=
• BETWEEN
• IN
• IS NULL
• IS NOT NULL
De plus, si l'opérateur de correspondance de modèle LIKE Le début de le modèle dans and~ n'est pas un caractère générique, et l'optimiseur peut également utiliser des index B-tree
, par exemple :

col LIKE 'foo%'
col ~ '^foo'

Pour les opérateurs ILIKE et ~* insensibles à la taille,
les index B-tree peuvent également être utilisés si le modèle de correspondance commence par un caractère non alphabétique (non affecté par la conversion de casse).
Les index B-tree peuvent également être utilisés pour optimiser les opérations de tri, telles que :

SELECT col1, col2
 FROM t
WHERE col1 BETWEEN 100 AND 200
ORDER BY col1;

L'index sur col1 peut non seulement optimiser les conditions de requête, mais également éviter des opérations de tri supplémentaires ; car lors d'un accès basé sur cet index,
les résultats sont renvoyés dans l'ordre trié.

Indice de hachage

L'index de hachage (Hash index) ne peut être utilisé que pour une simple recherche de valeur égale (=), ce qui signifie que le champ d'index est utilisé pour le
jugement de la condition de signe égal. Parce que la relation de taille d'origine n'est plus conservée après le hachage des données.
La création d'un index de hachage nécessite l'utilisation du mot clé HASH :

-- CREATE INDEX 语句用于创建索引,USING 子句指定索引的类型
CREATE INDEX index_name
ON table_name USING HASH (column_name);

Indice GiST

GiST signifie Generalized Search Tree. GiST indexe un seul type d'index, mais est un
cadre qui prend en charge différentes stratégies d'indexation. Les utilisations courantes des index GiST incluent l'indexation des données géométriques et la recherche en texte intégral. Les index GiST peuvent également
être utilisés pour optimiser les recherches du « voisin le plus proche », par ex.

-- 该语句用于查找距离某个目标地点最近的 10 个地方。
SELECT *
FROM places
ORDER BY location <-> point '(101,456)'
LIMIT 10;

Indice SP-GiST

SP-GiST signifie spatial partitionnement GiST, qui est principalement utilisé pour l'indexation de données telles que le SIG, le multimédia, le routage téléphonique et le routage IP.
Semblable à GiST, SP-GiST prend également en charge la recherche du « voisin le plus proche »

Indice GIN

GIN signifie index inversés généralisés et est principalement utilisé pour
les données contenant plusieurs valeurs dans un seul champ, telles que les types de données hstore, array, jsonb et range. Un index inversé crée une entrée d'index distincte
pour chaque valeur d'élément, vous permettant de demander efficacement si une valeur d'élément spécifique existe. Les moteurs de recherche tels que Google et Baidu utilisent
des index inversés.

Indice BRIN

BRIN signifie Block Range Index, qui stocke des informations récapitulatives sur les données dans des intervalles de plage physique continus.
BRIN est également beaucoup plus petit que les index B-tree et plus facile à maintenir.
Pour les très grandes tables qui ne peuvent pas utiliser les index B-tree sans partitionnement horizontal , BRIN peut être envisagé.
BRIN est généralement utilisé pour les champs avec un ordre de tri linéaire, comme la date de création de la table d'ordre.Introduction
aux index sur le site officiel de postgresql

Créer un index

PostgreSQL utilise l'instruction CREATE INDEX pour créer un nouvel index :

CREATE INDEX index_name ON table_name
[USING method]
(column_name [ASC | DESC] [NULLS FIRST | NULLS LAST]);

index_name est le nom de l'index, table_name est le nom de la table ;
• méthode indique le type d'index, tel que btree, hash, gist, spgist, gin ou brin. La valeur par défaut est btree ;
• column_name est le nom du champ, ASC représente l'ordre croissant (valeur par défaut), DESC représente l'index décroissant ;
• NULLS FIRST et NULLS LAST représentent l'ordre de tri des valeurs nulles dans l'index. La valeur par défaut est NULLS
LAST pour l'index croissant et la valeur par défaut pour l'index décroissant est NULLS FIRST.
Insérer la description de l'image ici

indice unique

Lors de la création d'un index, vous pouvez utiliser le mot-clé UNIQUE pour spécifier un index unique :

CREATE UNIQUE INDEX index_name
ON table_name (column_name [ASC | DESC] [NULLS FIRST | NULLS LAST]);

Les index uniques peuvent être utilisés pour implémenter des contraintes uniques. PostgreSQL ne prend actuellement en charge que les index uniques de type B-tree. Plusieurs valeurs NULL
sont considérées comme des valeurs différentes, donc les champs d'index uniques peuvent avoir plusieurs valeurs nulles.
Pour les clés primaires et les contraintes uniques, PostgreSQL créera automatiquement un index unique pour garantir l'unicité.

index multicolonne

CREATE [UNIQUE] INDEX index_name ON table_name
[USING method]
(column1 [ASC | DESC] [NULLS FIRST | NULLS LAST], ...);

Pour les index multicolonnes, les champs les plus couramment utilisés comme conditions de requête doivent être placés à gauche et les champs les moins couramment utilisés doivent être placés à droite.
Par exemple, un index créé sur la base de (c1, c2, c3) peut optimiser la requête suivante :

WHERE c1 = v1 and c2 = v2 and c3 = v3;
WHERE c1 = v1 and c2 = v2;
WHERE c1 = v1;

Mais la requête suivante ne peut pas utiliser cet index :

WHERE c2 = v2;
WHERE c3 = v3;
WHERE c2 = v2 and c3 = v3;

Pour un index unique multi-colonnes, les valeurs combinées des champs ne peuvent pas être répétées ; mais si un champ est une valeur nulle, des valeurs en double peuvent apparaître dans d'autres champs
.

indice de fonction

L'index de fonction, également appelé index d'expression, fait référence à un index créé en fonction de la valeur d'une fonction ou d'une expression.
La syntaxe de création d'un index fonctionnel dans PostgreSQL est la suivante

CREATE [UNIQUE] INDEX index_name
ON table_name (expression);

expression est une expression ou une fonction basée sur un champ.
La requête suivante utilise la fonction supérieure sur le champ de nom :
Insérer la description de l'image ici
虽然 name 字段上存在索引 test_name_index,但是函数会导致优化器无法使用该索引. Afin d'
optimiser cette instruction de requête insensible à la casse, vous pouvez基于 name 字段创建一个函数索引

drop index test_name_index;
create index test_name_index on test(upper(name));

Vérifiez à nouveau le plan d'exécution de cette instruction :
Insérer la description de l'image ici
le coût de maintenance des index fonctionnels est relativement élevé car des calculs de fonctions sont nécessaires à la fois pour l'insertion et la mise à jour.

index partiel

Un index partiel est un index créé pour une partie seulement des lignes de données de la table. Les lignes qui
doivent être indexées sont spécifiées via une clause WHERE. Par exemple, pour les commandes de la table des commandes, la plupart des commandes sont à l'état terminé ; il nous suffit d'
interroger et de suivre les commandes non terminées, et nous pouvons créer un index partiel.

-- 创建表
create table orders(order_id int primary key, order_ts timestamp, finished
boolean);

-- 创建索引
create index orders_unfinished_index
on orders (order_id)
WHERE finished is not true;

Cet index ne contient que les ID de commande inachevés, ce qui est beaucoup plus petit que l'index créé directement sur la base du champ terminé. Il peut être utilisé pour
optimiser les requêtes sur les commandes en cours :

explain analyze
select order_id
from orders
where finished is not true;

Insérer la description de l'image ici

indice de couverture

Les index dans PostgreSQL sont tous des index secondaires, ce qui signifie que l'index et les données sont stockés séparément. Par conséquent, la recherche de données via l'index
nécessite d'accéder à la fois à l'index et à la table, et l'accès à la table est aléatoire. Afin I/O
de résoudre ce problème de performances, PostgreSQL prend en charge l'analyse par index uniquement, qui n'a besoin que d'accéder aux données d'index pour
obtenir requise. Il n'est pas nécessaire d'accéder à nouveau aux données du tableau. Par exemple

-- 创建表
create table t (a int, b int, c int);
-- 创建唯一索引
create unique index idx_t_ab on t using btree (a, b) include (c);

L'instruction ci-dessus crée un index multi-colonnes basé sur les champs a et b et utilise INCLUDE pour stocker
la valeur du champ c dans le nœud feuille de l'index. Les requêtes suivantes peuvent tirer parti de l'analyse d'index uniquement :

explain analyze
select a, b, c
from t
where a = 100 and b = 200;

Insérer la description de l'image ici
La requête ci-dessus renvoie uniquement les champs d'index (a, b) et le champ couvert (c), et les résultats peuvent être renvoyés en analysant simplement l'index.
Les index B-tree prennent en charge l'analyse par index uniquement. Les index GiST et SP-GiST prennent en charge l'analyse par index uniquement pour certains opérateurs.
D'autres index ne prennent pas en charge cette méthode.

Afficher l'index

PostgreSQL fournit une vue sur les index pg_indexesqui peut être utilisée pour afficher les informations sur les index :

-- 该视图包含的字段依次为:模式名、表名、索引名、表空间以及索引的定义语句。
select * from pg_indexes where tablename = 'test';

Insérer la description de l'image ici

Maintenir l'index

PostgreSQL fournit plusieurs méthodes pour modifier et reconstruire les index :

ALTER INDEX index_name RENAME TO new_name;
ALTER INDEX index_name SET TABLESPACE tablespace_name;
REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } index_name;

Les deux instructions ALTER INDEX sont utilisées respectivement pour renommer l'index et déplacer l'index vers d'autres espaces table ; REINDEX est utilisé pour reconstruire
les données d'index et prend en charge différents niveaux de reconstruction d'index.

De plus, une fois l'index créé, le système mettra automatiquement à jour l'index tout en modifiant les données. Cependant, nous devons exécuter régulièrement
la commande ANALYZE pour mettre à jour les statistiques de la base de données afin que l'optimiseur puisse utiliser l'index de manière raisonnable.

Supprimer l'index

DROP INDEX index_name [ CASCADE | RESTRICT ];

CASCADE 表示级联删除其他依赖该索引的对象;RESTRICT 表示如果存在依赖于该索引 的对象,将会拒绝删除操作。默认为 RESTRICT

--可以使用以下语句删除 test 上的索引:
drop index test_id_index, test_name_index;

Je suppose que tu aimes

Origine blog.csdn.net/Java_Fly1/article/details/132843482
conseillé
Classement