SevenTnewS

Base de données

Comment la compression préfixe secondaire de PolarDB-X réduit le gonflement des index jusqu'à 70 %

Les index secondaires dominent souvent le stockage des bases de données, en particulier dans les systèmes SaaS et le commerce électronique. PolarDB-X introduit la compression préfixe secondaire (SPC), un schéma de dictionnaire par page léger qui réduit l'espace des index de 30 % à 70 % sans lourde charge CPU. Les benchmarks montrent une amélioration du débit allant jusqu'à 47 % dans les charges de travail de lecture liées aux E/S.

Emmanuel Fabrice Omgbwa Yasse Assisté par IA

2020-10-22 · Dernière mise à jour : 2026-07-16 · 7 min de lecture

Comment la compression préfixe secondaire de PolarDB-X réduit le gonflement des index jusqu'à 70 %

Pour les opérateurs de bases de données, les index secondaires sont une épée à double tranchant. Ils accélèrent les requêtes mais peuvent facilement consommer plus de stockage que la table primaire. Dans les systèmes multi-locataires SaaS, les plateformes de commerce électronique et les magasins de tracing distribué, les index représentent souvent plus de la moitié du stockage total de l'instance. Ce gonflement fait grimper les coûts, réduit l'efficacité du buffer pool, amplifie la pression sur les IOPS et augmente la contention sur les arbres B+.

L'équipe PolarDB-X d'Alibaba Cloud a publié un compte rendu technique détaillé d'un nouveau schéma de compression appelé Secondary Prefix Compression (SPC), implémenté dans le nœud de données (DN) du moteur de stockage. Contrairement à la compression à usage général appliquée au niveau du bloc, comme la compression de table intégrée d'InnoDB et la compression de page transparente, SPC exploite la redondance structurelle dans les pages feuilles des arbres B+ des index secondaires. Le résultat est un dictionnaire de préfixes léger et local à la page qui réduit l'espace des index de 30 % à 70 % tout en maîtrisant la charge CPU.

L'anatomie du gonflement des index

Dans InnoDB, chaque index secondaire stocke un tuple de la clé secondaire (SK) et de la clé primaire (PK). Comme les index sont triés par SK, les enregistrements adjacents au sein d'une page feuille ont tendance à partager de longs préfixes communs. Des champs tels que les identifiants de commande, les SKU, les URL, les chemins de fichiers et les identifiants de trace présentent une forte similarité de préfixe dans les charges de travail de production. Mais sous le format d'enregistrement COMPACT standard d'InnoDB, chaque enregistrement stocke sa SK complète indépendamment, même pour les enregistrements consécutifs avec la même SK, où seul le PK final diffère.

Cela est fonctionnellement correct mais spatialement gaspilleur. La redondance réduit l'utilisation de l'espace des pages feuilles, ce qui dilue la couverture des données chaudes du buffer pool, augmente la fréquence d'accès aux pages et élève le taux de divisions des arbres B+ et de contention sur les verrous SX. Les compresseurs de blocs à usage général comme zlib ou lz4 peuvent traiter le symptôme, mais leur coût de décompression à chaque lecture et, dans le cas de la compression de table, les doubles copies de pages en mémoire les rendent inadaptés aux charges de travail OLTP qui exigent un accès à faible latence.

SPC : dictionnaires de préfixes par page

SPC emprunte une voie différente. Au cœur du schéma se trouve un dictionnaire par page de préfixes communs, maintenu comme une petite zone de métadonnées au sein de chaque page d'index de 16 Ko. Chaque enregistrement ne stocke qu'une référence au dictionnaire, une longueur indiquant combien d'octets de ce préfixe il partage, et son propre suffixe restant. La valeur logique et l'ordre de tri de l'enregistrement restent inchangés, mais les préfixes répétés ne sont stockés qu'une fois par page.

Le tableau ci-dessous compare SPC avec les options de compression MySQL InnoDB existantes sur des dimensions clés :

FonctionnalitéCompression de tableCompression de page transparenteSPC
PortéeNiveau bloc (zlib)Niveau bloc (zlib/lz4)Dictionnaire de préfixes par page
Charge CPU5 % à 20 % (double copie en mémoire)5 % à 20 % (compression au moment des E/S)~2 % à 8 % (déclenché par division, comparaison directe)
Surcharge mémoireCopies compressée + décompresséeCopie uniqueCopie unique
Impact sur le buffer poolCapacité effective réduite de moitiéAucun supplémentAmélioré (plus d'enregistrements par page)
Amplification des écrituresRecompression à chaque écriture de pageCompression lors du vidageEncodage uniquement lors de la division de page
Ciblage des index secondairesNonNonOui

Le choix d'un dictionnaire partagé par page, par opposition aux préfixes delta par enregistrement ou à un dictionnaire partagé entre pages, est un compromis d'ingénierie délibéré. L'équipe PolarDB-X a évalué les trois approches et a conclu que la conception par page atteint le meilleur équilibre : la portée de la compression est strictement confinée à une seule page, évitant la gestion globale des métadonnées et l'amplification en cascade des écritures, tout en capturant la source dominante de redondance, la similarité des préfixes entre enregistrements adjacents.

Encodage déclenché par division et abstraction Slice

L'une des décisions de conception les plus pragmatiques de SPC est le moment de l'encodage. L'équipe a adopté une stratégie déclenchée par division : les enregistrements sont insérés dans leur forme non compressée. Ce n'est que lorsqu'une page est sur le point de manquer d'espace et de déclencher une division de l'arbre B+ que SPC encode toute la page. Cela signifie que les pages froides ou peu remplies n'encourent jamais de frais d'encodage, et le coût est amorti sur les centaines ou milliers d'opérations DML qui remplissent une page. De plus, l'espace libéré par la compression permet souvent à une insertion qui aurait provoqué une division de se terminer sur place ; la compression agit elle-même comme un soulagement de l'atténuation des divisions.

L'algorithme d'encodage lui-même est une approximation gloutonne en trois phases qui s'exécute en temps linéaire. Il analyse les enregistrements triés sur la page, les partitionne en intervalles de préfixes candidats en fonction des longueurs de préfixes communs, puis applique une heuristique de fusion pour équilibrer la taille du dictionnaire avec les économies nettes d'octets. Le dictionnaire est plafonné à 128 entrées, et les enregistrements dont le préfixe est trop court ou non couvert conservent leur forme originale ; les enregistrements compressés et non compressés coexistent sur la même page.

Sur le chemin de lecture, SPC introduit une abstraction Slice dans la couche de gestion des enregistrements d'InnoDB. Pour les enregistrements COMPACT standard, Slice dégénère en un accès direct par pointeur identique au comportement en amont. Pour les enregistrements SPC, il assemble paresseusement le préfixe du dictionnaire et le suffixe de l'enregistrement dans une région mémoire contiguë à la demande. De manière cruciale, l'abstraction supporte également la décompression partielle : lors de la comparaison d'un enregistrement SPC avec un tuple de requête, la comparaison peut être effectuée colonne par colonne directement sous forme compressée, en utilisant l'entrée du dictionnaire et les décalages étendus, sans reconstruire d'abord un enregistrement complet décompressé. Cela élimine une opération memcpy et une allocation temporaire sur le chemin de lecture à chaud.

La couche Slice garantit que SPC est sémantiquement opaque pour le reste d'InnoDB ; tous les chemins de code en amont (MVCC, undo, purge, verrouillage, change buffer, réplication, sauvegarde/restauration) continuent de fonctionner inchangés. De l'extérieur, SPC est purement une optimisation de stockage physique au sein de la page.

Résultats des benchmarks : jusqu'à 47 % de gains de débit sous pression E/S

L'équipe PolarDB-X a mené une série de benchmarks sysbench en utilisant un schéma de table conçu pour simuler des caractéristiques typiques de répétition de préfixes : 3 colonnes INT à faible cardinalité, 6 colonnes VARCHAR(64) avec un préfixe commun de 40 octets, et 12 index secondaires. Avec SPC désactivé, une table unique de 1 million de lignes occupait 1,8 Go, dont les index secondaires consommaient 1,16 Go. Avec SPC activé, la table a rétréci à 1,1 Go, avec des index secondaires à 0,52 Go, soit une compression de 55 % sur les index secondaires et de 38 % au total.

Les résultats les plus frappants sont venus dans des conditions liées aux E/S avec un buffer pool de 4 Go (couvrant environ 30 % de l'ensemble de données sans SPC) :

Charge de travailSPC désactivé (QPS)SPC activé (QPS)Amélioration
read_only82 401108 384+31,5 %
read_write33 29234 060+2,3 %
write_only20 25920 615+1,8 %

Avec un buffer pool de 8 Go, doublant la couverture à près de 50 %, les améliorations dans les charges de travail liées aux E/S de lecture ont bondi à +46,8 % pour read_only et +47,5 % pour read_write. La charge de travail write_only est restée pratiquement stable (+1,6 %) car son chemin de lecture localise les lignes par clé primaire et ne parcourt jamais les pages d'index secondaires, tandis que l'encodage déclenché par division garantit que les DML de routine n'encourent pas de frais d'encodage.

Avec le buffer pool réglé sur 32 Go, suffisamment grand pour que l'ensemble de données réside en mémoire, l'avantage en matière d'E/S a disparu. Les différences entre les trois charges de travail se situaient dans une fourchette de ±2,4 %, confirmant que la surcharge de décompression de SPC sur le chemin CPU pur est minimale et que son impact en écriture est négligeable.

Comparaison avec d'autres bases de données

Parmi les principaux systèmes de bases de données, la compression de page de Microsoft SQL Server est la plus proche en esprit de SPC : elle applique un pipeline en trois couches de compression de ligne, de compression de préfixe et de compression de dictionnaire, déclenché lorsqu'une page se remplit. La déduplication des arbres B de PostgreSQL consolide les clés en double mais ne gère pas le partage partiel de préfixes. La compression d'index avancée d'Oracle utilise une compression adaptative par bloc, tandis que sa compression de préfixe de base (COMPRESS n) opère au niveau de la colonne. La précision au niveau de l'octet de SPC lui confère une granularité plus fine que l'approche au niveau de la colonne d'Oracle, et son confinement aux index secondaires, où la redondance est la plus élevée, en fait une optimisation ciblée plutôt qu'un compresseur universel.

Conclusion

SPC n'est pas une rupture radicale avec les techniques de compression de bases de données existantes, mais c'est une optimisation bien exécutée et pratique qui répond à un point sensible spécifique : le gonflement des index secondaires dans les charges de travail OLTP. En restreignant la compression aux dictionnaires de préfixes par page déclenchés uniquement au moment de la division de page, l'équipe PolarDB-X a réussi à réduire le stockage des index de 30 % à 70 % tout en maintenant les coûts de CPU et de complexité suffisamment bas pour un déploiement en production. Pour les opérateurs cloud exécutant déjà des charges de travail compatibles MySQL sur PolarDB-X d'Alibaba Cloud, SPC offre un levier significatif pour réduire les factures de stockage et améliorer les performances des requêtes liées aux E/S, sans modifications de l'application.

Pour la communauté plus large de l'ingénierie des bases de données, la leçon est que la redondance structurelle dans les pages triées des arbres B+ est un filon riche à exploiter, et qu'une approche légère et étroitement ciblée peut surpasser les compresseurs à usage général lourds dans la zone de prédilection des OLTP. Les détails techniques complets sont disponibles dans l'article de blog de l'équipe PolarDB-X.

L'essentiel de la tech en 3 minutes chaque matin

Un email, chaque jour ouvré, avec ce qui compte vraiment en IA et en tech.