Exécutez EXPLAIN sur une requête SQL pour vérifier si PolarDB utilise des index columnaires en mémoire (IMCI) pour l'accélérer. Les requêtes accélérées par IMCI produisent un format de plan d'exécution distinct, immédiatement identifiable.
Prérequis
Avant de commencer, assurez-vous de disposer des éléments suivants :
Un nœud de stockage en colonnes en lecture seule ajouté à votre cluster PolarDB for MySQL
Des IMCI créés sur les tables référencées dans vos requêtes
Un endpoint de cluster avec l'option Transactional/Analytical Processing Splitting activée
Lecture des plans d'exécution IMCI
Lorsqu'une requête s'exécute sur le nœud de stockage en colonnes à l'aide des IMCI, la sortie EXPLAIN passe du format de table MySQL standard à un format d'arborescence horizontale.
Indicateur clé : Recherchez la mention IMCI Execution Plan dans la colonne Extra Info de la première ligne. La présence de cette chaîne confirme que les IMCI accélèrent la requête. Si la sortie conserve le format de table standard sans cet en-tête, la requête s'exécute sur des index de stockage en lignes.
Requête SQL utilisée dans les exemples ci-dessous :
EXPLAIN SELECT l_orderkey, SUM(l_extendedprice * (1 - l_discount)) AS revenue, o_orderdate, o_shippriority
FROM customer, orders, lineitem
WHERE c_mktsegment = 'BUILDING'
AND c_custkey = o_custkey
AND l_orderkey = o_orderkey
AND o_orderdate < date '1995-03-24'
AND l_shipdate > date '1995-03-24'
GROUP BY l_orderkey, o_orderdate, o_shippriority
ORDER BY revenue DESC, o_orderdate;
Plan d'exécution en stockage de lignes — format de table MySQL standard, sans accélération IMCI :
+----+-------------+----------+------------+------+--------------------+------------+---------+-----------------------------+--------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+--------------------+------------+---------+-----------------------------+--------+----------+----------------------------------------------+
| 1 | SIMPLE | customer | NULL | ALL | PRIMARY | NULL | NULL | NULL | 147630 | 10.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | orders | NULL | ref | PRIMARY,ORDERS_FK1 | ORDERS_FK1 | 4 | tpch100g.customer.C_CUSTKEY | 14 | 33.33 | Using where |
| 1 | SIMPLE | lineitem | NULL | ref | PRIMARY | PRIMARY | 4 | tpch100g.orders.O_ORDERKEY | 4 | 33.33 | Using where |
+----+-------------+----------+------------+------+--------------------+------------+---------+-----------------------------+--------+----------+----------------------------------------------+
3 rows in set, 1 warning (0.00 sec)
Plan d'exécution en stockage de colonnes — format d'arborescence horizontale, accélération IMCI confirmée :
+----+----------------------------+----------+--------+--------+-----------------------------------------------------------------------------+
| ID | Operator | Name | E-Rows | E-Cost | Extra Info |
+----+----------------------------+----------+--------+--------+-----------------------------------------------------------------------------+
| 1 | Select Statement | | | | IMCI Execution Plan (max_dop = 4, max_query_mem = 858993459) |
| 2 | └─Sort | | | | Sort Key: revenue DESC,o_orderdate ASC |
| 3 | └─Hash Groupby | | | | Group Key: (lineitem.L_ORDERKEY, orders.O_ORDERDATE, orders.O_SHIPPRIORITY) |
| 4 | └─Hash Join | | | | Join Cond: orders.O_ORDERKEY = lineitem.L_ORDERKEY |
| 5 | ├─Hash Join | | | | Join Cond: customer.C_CUSTKEY = orders.O_CUSTKEY |
| 6 | │ ├─Table Scan | customer | | | Cond: (C_MKTSEGMENT = "BUILDING") |
| 7 | │ └─Table Scan | orders | | | Cond: (O_ORDERDATE < 03/24/1995) |
| 8 | └─Table Scan | lineitem | | | Cond: (L_SHIPDATE > 03/24/1995) |
+----+----------------------------+----------+--------+--------+-----------------------------------------------------------------------------+
8 rows in set (0.01 sec)
Vérifier la couverture IMCI avant d'exécuter des requêtes
Un IMCI n'accélère une requête que s'il couvre toutes les colonnes qui y sont référencées. Si une table ou une colonne n'est pas couverte, l'IMCI ne prend pas effet.
Pour vérifier si les IMCI de votre cluster couvrent toutes les colonnes d'une instruction SQL, appelez dbms_imci.check_columnar_index() :
CALL dbms_imci.check_columnar_index('SELECT COUNT(*) FROM t1 WHERE t1.a > 1');
Si toutes les colonnes sont couvertes, la procédure stockée renvoie un ensemble de résultats vide.
Si certaines colonnes ne sont pas couvertes, la procédure stockée retourne les tables et colonnes concernées. Créez des IMCI pour ces colonnes avant d'exécuter la requête.
Pour obtenir l'instruction DDL permettant de créer un IMCI couvrant toutes les colonnes d'une requête, appelez dbms_imci.columnar_advise() :
dbms_imci.columnar_advise('<query_string>');
Pour plus d'informations, consultez Vérifier si un IMCI est créé pour une table dans une instruction SQL et Obtenir l'instruction DDL utilisée pour créer un IMCI.
FAQ
Pourquoi ma requête n'utilise-t-elle pas les IMCI ?
Une requête bénéficie de l'accélération IMCI uniquement lorsque les quatre conditions suivantes sont réunies :
Un nœud de stockage en colonnes en lecture seule est présent dans le cluster
Des IMCI existent sur toutes les tables référencées dans la requête
Le coût d'exécution estimé de la requête dépasse le seuil configuré
La requête est routée vers le nœud de stockage en colonnes en lecture seule
Suivez les étapes ci-dessous pour identifier quelle condition n'est pas remplie.
Étape 1 : Vérifier que la requête atteint le nœud de stockage en colonnes
Vérifiez si le nœud de stockage en colonnes en lecture seule figure dans les selected nodes de l'endpoint du cluster. Utilisez SQL Explorer pour confirmer que la requête a bien été routée vers ce nœud.
PolarProxy route une requête vers le nœud de stockage en colonnes uniquement lorsque :
La requête se connecte via l'cluster endpoint
L'option Transactional/Analytical Processing Splitting est activée pour l'endpoint du cluster
Le coût estimé de la requête dépasse le seuil défini par
loose_imci_ap_threshold(ouloose_cost_threshold_for_imcidans les versions antérieures du moteur)
Pour forcer le routage d'une requête vers le nœud de stockage en colonnes à des fins de test, ajoutez le hint /*FORCE_IMCI_NODES*/ avant le mot-clé SELECT :
/*FORCE_IMCI_NODES*/EXPLAIN SELECT COUNT(*) FROM t1 WHERE t1.a > 1;
Vous pouvez également créer un endpoint personnalisé associé au nœud de stockage en colonnes pour garantir le routage. Pour plus d'informations, consultez Distribution des requêtes basée sur HTAP entre les nœuds de stockage en lignes et en colonnes.
Le paramètreloose_imci_ap_thresholdremplaceloose_cost_threshold_for_imcidans les versions mineures du moteur 8.0.1.1.39 ou ultérieures, ainsi que 8.0.2.2.23 ou ultérieures.
Étape 2 : Vérifier si le coût de la requête atteint le seuil
Sur le nœud de stockage en colonnes, l'optimiseur estime le coût d'exécution de la requête. Si cette estimation dépasse le seuil défini par loose_imci_ap_threshold ou cost_threshold_for_imci, l'optimiseur utilise les IMCI. Dans le cas contraire, il revient aux index de stockage en lignes.
Si EXPLAIN affiche un plan de stockage en lignes alors même que la requête atteint le nœud de stockage en colonnes, comparez le coût estimé au seuil :
-- View the execution plan
EXPLAIN SELECT * FROM t1;
-- Get the estimated cost of the previous query
SHOW STATUS LIKE 'Last_query_cost_for_imci';
En cas de connexion via l'endpoint du cluster, ajoutez/*ROUTE_TO_LAST_USED*/pour lire le coût depuis le bon nœud :/*ROUTE_TO_LAST_USED*/SHOW STATUS LIKE 'Last_query_cost_for_imci';
Si le coût estimé est inférieur au seuil, ajustez le paramètre loose_imci_ap_threshold ou loose_cost_threshold_for_imci, ou contournez le seuil pour une requête unique à l'aide d'un hint :
/*FORCE_IMCI_NODES*/EXPLAIN SELECT /*+ SET_VAR(cost_threshold_for_imci=0) */ COUNT(*) FROM t1 WHERE t1.a > 1;
Pour plus d'informations, consultez Spécifier les seuils pour la distribution automatique des requêtes.
Étape 3 : Vérifier la couverture des colonnes par l'IMCI
Appelez dbms_imci.check_columnar_index() pour vérifier que les IMCI couvrent toutes les tables et colonnes de la requête :
CALL dbms_imci.check_columnar_index('SELECT COUNT(*) FROM t1 WHERE t1.a > 1');
Si la procédure stockée retourne des tables ou des colonnes non couvertes, créez des IMCI correspondants. Un ensemble de résultats vide indique que toutes les colonnes sont couvertes.
Étape 4 : Vérifier les limites d'utilisation des IMCI
Certains modèles de requêtes ne sont pas pris en charge par les IMCI. Consultez les Limites d'utilisation des IMCI pour confirmer l'éligibilité de la requête.
Si la requête n'utilise toujours pas les IMCI après avoir suivi ces quatre étapes, reportez-vous aux Meilleures pratiques IMCI ou contactez le support technique.
Comment créer l'IMCI adapté à une requête ?
Une requête utilise un IMCI uniquement si celui-ci couvre toutes les colonnes qu'elle référence. Utilisez dbms_imci.columnar_advise() pour générer l'instruction DDL permettant de créer un IMCI couvrant toutes les colonnes d'une requête donnée :
dbms_imci.columnar_advise('<query_string>');
Pour générer des instructions DDL pour un lot de requêtes, utilisez conjointement dbms_imci.columnar_advise_begin(), dbms_imci.columnar_advise() et dbms_imci.columnar_advise_end(). Pour plus d'informations, consultez Obtenir par lots les instructions DDL utilisées pour créer des IMCI.
Si les colonnes d'une requête ne sont pas entièrement couvertes, utilisez ALTER TABLE pour ajouter les colonnes manquantes à un IMCI existant, ou exécutez l'instruction DDL issue de columnar_advise() pour en créer un nouveau.