Les profils de requête capturent les détails d'exécution par nœud pour chaque requête. Utilisez-les pour identifier les goulots d'étranglement et optimiser les performances.
Activer les profils de requête
Définissez la variable enable_profile pour lancer la collecte des profils :
SET enable_profile=true;
Lorsque
enable_profile
est défini sur
true
, SelectDB génère un profil pour chaque requête exécutée. Chaque profil enregistre les détails d'exécution sur l'ensemble des nœuds.
Consulter les profils de requête
L'instruction SHOW QUERY PROFILE est prise en charge uniquement pour les versions de SelectDB Core antérieures à V4.0.0. Pour SelectDB Core V4.0.0 et ultérieures, prévisualisez ou téléchargez les profils de requête depuis la console SelectDB, ou utilisez l'API HTTP. Pour plus de détails, reportez-vous à Utiliser la fonctionnalité d'audit de requête et Exporter les profils de requête.
Exécutez l'instruction suivante pour répertorier tous les profils stockés :
SHOW QUERY PROFILE "/"\G;
Chaque ligne du résultat correspond à un profil :
SHOW QUERY PROFILE "/"\G
*************************** 1. row ***************************
Profile ID: c257c52f93e149ee-ace8ac14e8c9fef9
Task Type: QUERY
Start Time: 2021-04-08 11:30:50
End Time: 2021-04-08 11:30:50
Total: 9ms
Task State: EOF
User: root
Default Db: default_cluster:db1
Sql Statement: select tbl1.k1, sum(tbl1.k2) from tbl1 join tbl2 on tbl1.k1 = tbl2.k1 group by tbl1.k1 order by tbl1.k1
Dans les réponses de l'API HTTP, les champs
Query ID
et
query_id
font référence à l'ID du profil.
Analyser les profils de requête
Suivez ce processus en trois étapes pour localiser le goulot d'étranglement d'une requête. Chaque étape permet d'approfondir l'analyse d'un niveau dans la hiérarchie d'exécution.
Étape 1 : Identifier le fragment le plus lent
Objectif : Trouver le fragment qui constitue le goulot d'étranglement principal.
L'arborescence du plan d'exécution affiche la structure des fragments ainsi que leur temps d'exécution. La valeur MaxActiveTime de chaque nœud expéditeur correspond au temps d'exécution le plus long parmi toutes les unités d'exécution de ce fragment.
SHOW QUERY PROFILE "/<profile_id>"\G
Exemple de sortie :
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9"\G
*************************** 1. row ***************************
Fragments:
┌──────────────────────┐
│[-1: DataBufferSender]│
│Fragment: 0 │
│MaxActiveTime: 6.626 ms│
└──────────────────────┘
│
┌──────────────────┐
│[9: EXCHANGE_NODE]│
│Fragment: 0 │
└──────────────────┘
│
┌──────────────────────┐
│[9: DataStreamSender] │
│Fragment: 1 │
│MaxActiveTime: 5.449 ms│
└──────────────────────┘
│
┌──────────────┐
│[4: SORT_NODE]│
│Fragment: 1 │
└──────────────┘
┌┘
┌─────────────────────┐
│[8: AGGREGATION_NODE]│
│Fragment: 1 │
└─────────────────────┘
└┐
┌──────────────────┐
│[7: EXCHANGE_NODE]│
│Fragment: 1 │
└──────────────────┘
│
┌──────────────────────┐
│[7: DataStreamSender] │
│Fragment: 2 │
│MaxActiveTime: 3.505 ms│
└──────────────────────┘
┌┘
┌─────────────────────┐
│[3: AGGREGATION_NODE]│
│Fragment: 2 │
└─────────────────────┘
│
┌───────────────────┐
│[2: HASH_JOIN_NODE]│
│Fragment: 2 │
└───────────────────┘
┌────────────┴────────────┐
┌──────────────────┐ ┌──────────────────┐
│[5: EXCHANGE_NODE]│ │[6: EXCHANGE_NODE]│
│Fragment: 2 │ │Fragment: 2 │
└──────────────────┘ └──────────────────┘
│ │
┌─────────────────────┐ ┌────────────────────────┐
│[5: DataStreamSender]│ │[6: DataStreamSender] │
│Fragment: 4 │ │Fragment: 3 │
│MaxActiveTime: 1.87 ms│ │MaxActiveTime: 636.767 us│
└─────────────────────┘ └────────────────────────┘
│ ┌┘
┌───────────────────┐ ┌───────────────────┐
│[0: OLAP_SCAN_NODE]│ │[1: OLAP_SCAN_NODE]│
│Fragment: 4 │ │Fragment: 3 │
└──────────────────┘ └──────────────────┘
│ │
┌─────────────┐ ┌─────────────┐
│[OlapScanner]│ │[OlapScanner]│
│Fragment: 4 │ │Fragment: 3 │
└─────────────┘ └─────────────┘
│ │
┌─────────────────┐ ┌─────────────────┐
│[SegmentIterator]│ │[SegmentIterator]│
│Fragment: 4 │ │Fragment: 3 │
└─────────────────┘ └─────────────────┘
1 row in set (0.02 sec)
Dans cet exemple, le Fragment 1 présente la valeur MaxActiveTime la plus élevée (5,449 ms) ; il s'agit donc du goulot d'étranglement principal. Passez à l'étape 2 en analysant le Fragment 1.
Étape 2 : Identifier l'unité d'exécution la plus lente
Objectif : Déterminer quelle instance de nœud, au sein du fragment identifié, consomme le plus de temps.
Une fois le fragment le plus lent identifié, listez toutes les unités d'exécution (instances) qu'il contient :
SHOW QUERY PROFILE "/<profile_id>/<fragment_id>";
Exemple de sortie pour le Fragment 1 :
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9/1";
+-----------------------------------+-------------------+------------+
| Instances | Host | ActiveTime |
+-----------------------------------+-------------------+------------+
| c257c52f93e149ee-ace8ac14e8c9ff03 | 10.200.00.01:9060 | 5.449ms |
| c257c52f93e149ee-ace8ac14e8c9ff05 | 10.200.00.02:9060 | 5.367ms |
| c257c52f93e149ee-ace8ac14e8c9ff04 | 10.200.00.03:9060 | 5.358ms |
+-----------------------------------+-------------------+------------+
L'instance affichant la valeur ActiveTime la plus élevée sera votre cible pour l'étape 3.
Étape 3 : Inspecter les métriques par opérateur
Objectif : Déterminer quel opérateur consomme le plus de temps et de ressources sur l'unité d'exécution cible.
SHOW QUERY PROFILE "/<profile_id>/<fragment_id>/<instance_id>"\G
Exemple de sortie pour l'instance c257c52f93e149ee-ace8ac14e8c9ff03 du Fragment 1 :
SHOW QUERY PROFILE "/c257c52f93e149ee-ace8ac14e8c9fef9/1/c257c52f93e149ee-ace8ac14e8c9ff03"\G
*************************** 1. row ***************************
Instance:
┌───────────────────────────────────────┐
│[9: DataStreamSender] │
│(Active: 37.222 us, non-child: 0.40) │
│ - Counters: │
│ - BytesSent: 0.00 │
│ - IgnoreRows: 0 │
│ - OverallThroughput: 0.0 /sec │
│ - PeakMemoryUsage: 8.00 KB │
│ - SerializeBatchTime: 0ns │
│ - UncompressedRowBatchSize: 0.00 │
└───────────────────────────────────────┘
└┐
│
┌──────────────────────────────────┐
│[4: SORT_NODE] │
│(Active: 5.421 ms, non-child: 0.71)│
│ - Counters: │
│ - PeakMemoryUsage: 12.00 KB │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
└──────────────────────────────────┘
┌┘
│
┌───────────────────────────────────┐
│[8: AGGREGATION_NODE] │
│(Active: 5.355 ms, non-child: 10.68)│
│ - Counters: │
│ - BuildTime: 3.701us │
│ - GetResultsTime: 0 ns │
│ - HTResize: 0 │
│ - HTResizeTime: 1.211 us │
│ - HashBuckets: 0 │
│ - HashCollisions: 0 │
│ - HashFailedProbe: 0 │
│ - HashFilledBuckets: 0 │
│ - HashProbe: 0 │
│ - HashTravelLength: 0 │
│ - LargestPartitionPercent: 0 │
│ - MaxPartitionLevel: 0 │
│ - NumRepartitions: 0 │
│ - PartitionsCreated: 16 │
│ - PeakMemoryUsage: 34.02 MB │
│ - RowsProcessed: 0 │
│ - RowsRepartitioned: 0 │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
│ - SpilledPartitions: 0 │
└───────────────────────────────────┘
└┐
│
┌──────────────────────────────────────────┐
│[7: EXCHANGE_NODE] │
│(Active: 4.360 ms, non-child: 46.84) │
│ - Counters: │
│ - BytesReceived: 0.00 │
│ - ConvertRowBatchTime: 387 ns │
│ - DataArrivalWaitTime: 4.357 ms │
│ - DeserializeRowBatchTimer: 0 ns │
│ - FirstBatchArrivalWaitTime: 4.356 ms│
│ - PeakMemoryUsage: 0.00 │
│ - RowsReturned: 0 │
│ - RowsReturnedRate: 0 │
│ - SendersBlockedTotalTimer(*): 0 ns │
└──────────────────────────────────────────┘
Un pourcentage Active élevé associé à un pourcentage non-child important sur un nœud indique que ce nœud est lui-même le goulot d'étranglement (et non un opérateur enfant). Concentrez vos efforts d'optimisation sur ce point.
Exporter les profils de requête
L'exportation des profils de requête nécessite SelectDB Core V3.0.4 ou version ultérieure.
Exportez un profil vers un fichier pour une analyse hors ligne ou pour le partager.
-
Activez les profils de requête.
SET enable_profile=true; -
Exécutez la requête à profiler.
-- Run your target query. SelectDB generates a profile for it. SELECT count(1) FROM test_table LIMIT 10; -
Récupérez l'ID du profil.
Versions SelectDB 4.0.x
Envoyez une requête HTTP pour obtenir les informations de requête. Le champ
Query IDdans la réponse correspond à l'ID du profil.curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/rest/v2/manager/query/query_info?is_all_node=true"Exemple de réponse :
{ "msg": "success", "code": 0, "data": { "column_names": [ "Query ID", "FE Node", "Query User", "Execution Database", "Sql", "Query Type", "Start Time", "End Time", "Execution Duration", "Status" ], "rows": [ [ ... ] ] }, "count": 0 }Versions SelectDB 3.0.x
L'exemple suivant montre comment procéder avec SelectDB 3.0 :
SHOW QUERY PROFILE "/";Exemple de sortie :
+-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ | Profile ID | Task Type | Start Time | End Time | Total | Task State | User | Default Db | Sql Statement | +-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ | b9c9ba063d9d4365-97878361371e757a | QUERY | 2024-02-07 17:40:04 | 2024-02-07 17:40:04 | 32ms | EOF | admin | default_cluster:information_schema | select * from user_privileges | | 8800c306137e4072-9bb1ed419f4ac9f2 | QUERY | 2024-02-07 17:40:00 | 2024-02-07 17:40:00 | 3ms | ERR | admin | default_cluster:information_schema | select * from user_priveleges | | e2efdd1a996c4de2-ab939ad49b409990 | QUERY | 2024-02-07 17:39:51 | 2024-02-07 17:39:51 | 13ms | EOF | admin | | SELECT DATABASE() | +-----------------------------------+-----------+---------------------+---------------------+-------+------------+-------+------------------------------------+-------------------------------+ -
Exportez le profil à l'aide de son ID.
Espace réservé Description Valeur par défaut <userName>Nom d'utilisateur pour accéder à l'instance SelectDB — <userPassword>Mot de passe pour accéder à l'instance SelectDB — <selectdbAddress>Endpoint de l'instance SelectDB — <httpPort>Numéro de port HTTP 8080 <query_id>ID du profil obtenu à l'étape 3 — curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/api/profile?query_id=<query_id>"Pour enregistrer la sortie dans un fichier, redirigez la réponse :
curl -u'<userName>:<userPassword>' \ "http://<selectdbAddress>:<httpPort>/api/profile?query_id=<query_id>" > res.txtRemplacez les espaces réservés suivants par vos valeurs réelles :
-
(Facultatif) Formatez le fichier exporté pour en améliorer la lisibilité.
sudo sed -r 's/\\n/\n/g' res.txt | sed -r 's/\\t/\t/g' > new.txt
Référence des paramètres de profil
Les tableaux suivants décrivent l'ensemble des paramètres collectés dans un profil de requête.
Fragment
| Paramètre | Description |
|---|---|
AverageThreadTokens |
Nombre de threads utilisés pour l'exécution du fragment, hors utilisation du pool de threads. |
Buffer Pool PeakReservation |
Utilisation mémoire maximale du buffer pool. |
MemoryLimit |
Limite de mémoire allouée à la requête. |
PeakMemoryUsage |
Consommation mémoire maximale d'une unité d'exécution durant la requête. |
RowsProduced |
Nombre de lignes dont les colonnes ont été traitées. |
BlockMgr
| Paramètre | Description |
|---|---|
BlocksCreated |
Nombre de blocs créés par le BlockManager. |
BlocksRecycled |
Nombre de blocs réutilisés. |
BytesWritten |
Taille totale des données écrites sur disque. |
MaxBlockSize |
Taille d'un bloc unique. |
TotalReadBlockTime |
Temps total consacré à la lecture des blocs. |
DataStreamSender
| Paramètre | Description |
|---|---|
BytesSent |
Taille totale des données envoyées. Calcul : nombre de destinataires × taille des données envoyées. |
IgnoreRows |
Nombre de lignes filtrées. |
LocalBytesSent |
Volume de données transmises par le nœud local et reçues par ce même nœud lors de l'échange de données. |
OverallThroughput |
Débit global. Calcul : BytesSent / temps d'exécution. |
SerializeBatchTime |
Temps nécessaire à la sérialisation des données avant envoi. |
UncompressedRowBatchSize |
Taille des données RowBatch envoyées avant compression. |
ODBC_TABLE_SINK
| Paramètre | Description |
|---|---|
NumSentRows |
Nombre total de lignes écrites dans une table externe. |
TupleConvertTime |
Temps consacré à la sérialisation des données envoyées sous forme d'instructions INSERT. |
ResultSendTime |
Temps consacré à l'écriture des données via le pilote Open Database Connectivity (ODBC). |
EXCHANGE_NODE
| Paramètre | Description |
|---|---|
BytesReceived |
Volume de données reçues via le réseau. |
MergeGetNext |
Si un tri est effectué sur le nœud enfant, le nœud d'échange réalise une fusion et un tri unifiés. Cette métrique représente le temps total de cette opération, y compris MergeGetNextBatch. |
MergeGetNextBatch |
Temps nécessaire au nœud de fusion pour récupérer les données. Pour une fusion et un tri à un seul niveau, les données proviennent d'une file d'attente réseau. Pour une fusion et un tri multiniveaux, elles proviennent d'un fusionneur enfant. |
ChildMergeGetNext |
Lorsque de nombreux expéditeurs transmettent des données, la fusion monothread devient un goulot d'étranglement. ApsaraDB for SelectDB lance alors plusieurs threads sur le nœud de fusion enfant pour effectuer la fusion et le tri en parallèle. Cette valeur cumule le temps de tous les threads. |
ChildMergeGetNextBatch |
Temps nécessaire au nœud de fusion enfant pour récupérer les données. Des valeurs élevées peuvent signaler des goulots d'étranglement au niveau du nœud d'envoi enfant. |
DataArrivalWaitTime |
Temps d'attente total pour la réception des données depuis l'expéditeur. |
FirstBatchArrivalWaitTime |
Délai d'attente avant la réception du premier lot de données de l'expéditeur. |
DeserializeRowBatchTimer |
Temps consacré à la désérialisation des données réseau. |
SendersBlockedTotalTimer(*) |
Temps d'attente cumulé côté expéditeur lorsque la mémoire de la file DataStreamRecv est saturée. |
ConvertRowBatchTime |
Temps nécessaire pour convertir les données reçues en RowBatch. |
RowsReturned |
Nombre de lignes reçues. |
RowsReturnedRate |
Taux de réception des lignes. |
SORT_NODE
| Paramètre | Description |
|---|---|
InMemorySortTime |
Temps consacré au tri en mémoire. |
InitialRunsCreated |
Nombre d'initialisations du tri. La valeur est 1 pour un tri en mémoire. |
SortDataSize |
Taille totale des données triées. |
MergeGetNext |
Temps nécessaire à MergeSort pour obtenir le lot suivant à partir de plusieurs séquences triées. Mesuré uniquement lors de l'écriture sur disque. |
MergeGetNextBatch |
Temps nécessaire à MergeSort pour extraire le lot de la prochaine séquence triée. Mesuré uniquement lors de l'écriture sur disque. |
TotalMergesPerformed |
Nombre de fusions externes effectuées. |
AGGREGATION_NODE
| Paramètre | Description |
|---|---|
PartitionsCreated |
Nombre de partitions générées par la division de la requête d'agrégation. |
GetResultsTime |
Temps nécessaire pour récupérer les résultats d'agrégation depuis les partitions. |
HTResizeTime |
Temps consacré au redimensionnement de la table de hachage. |
HTResize |
Nombre de redimensionnements de la table de hachage. |
HashBuckets |
Nombre de compartiments (buckets) dans la table de hachage. |
HashBucketsWithDuplicate |
Nombre de compartiments contenant des nœuds dupliqués dans la table de hachage. |
HashCollisions |
Nombre de collisions de hachage dans la table. |
HashDuplicateNodes |
Nombre de nœuds dupliqués appartenant au même compartiment dans la table de hachage. |
HashFailedProbe |
Nombre d'opérations de sondage échouées sur la table de hachage. |
HashFilledBuckets |
Nombre de compartiments remplis de données dans la table de hachage. |
HashProbe |
Nombre de requêtes effectuées sur la table de hachage. |
HashTravelLength |
Nombre de déplacements effectués lors d'une requête sur la table de hachage. |
HASH_JOIN_NODE
| Paramètre | Description |
|---|---|
ExecOption |
Méthode de construction de la table de hachage pour le nœud enfant droit : synchrone ou asynchrone. |
BuildBuckets |
Nombre de compartiments dans la table de hachage. |
BuildRows |
Nombre de lignes dans la table de hachage. |
BuildTime |
Temps consacré à la construction de la table de hachage. |
LoadFactor |
Facteur de charge de la table de hachage, indiquant le nombre de compartiments non vides. |
ProbeRows |
Nombre de lignes sur lesquelles l'opération de sondage de hachage est effectuée après le parcours des nœuds enfants gauches. |
ProbeTime |
Temps consacré au parcours des nœuds enfants gauches pour le sondage de hachage, hors temps d'appel à GetNext sur RowBatch depuis le nœud enfant gauche. |
PushDownComputeTime |
Temps consacré au calcul des conditions de pushdown de prédicats. |
PushDownTime |
Temps total consacré au pushdown de prédicats. Les requêtes JOIN sur les nœuds enfants droits qui satisfont aux conditions sont converties en requêtes IN sur les nœuds enfants gauches. |
CROSS_JOIN_NODE
| Paramètre | Description |
|---|---|
ExecOption |
Méthode de construction de la RowBatchList pour le nœud enfant droit : synchrone ou asynchrone. |
BuildRows |
Nombre de lignes de la RowBatchList (lignes du nœud enfant droit). |
BuildTime |
Temps consacré à la construction de la RowBatchList. |
LeftChildRows |
Nombre de lignes dans le nœud enfant gauche. |
LeftChildTime |
Temps consacré au parcours des nœuds enfants gauche et droit pour générer le produit cartésien, hors temps d'appel à GetNext sur RowBatch depuis le nœud enfant gauche. |
UNION_NODE
| Paramètre | Description |
|---|---|
MaterializeExprsEvaluateTime |
Temps consacré à l'évaluation des expressions de conversion de type et à la matérialisation des résultats lorsque les types de champs diffèrent de part et d'autre d'un UNION. |
ANALYTIC_EVAL_NODE
| Paramètre | Description |
|---|---|
EvaluationTime |
Temps total consacré au calcul des fonctions analytiques (fonctions de fenêtrage). |
GetNewBlockTime |
Temps consacré à l'allocation d'un nouveau bloc lors de l'initialisation. Ce bloc met en cache la fenêtre Rows ou une partition entière pour le calcul de la fonction analytique. |
PinTime |
Temps consacré à l'allocation d'un nouveau bloc ou à la relecture en mémoire d'un bloc précédemment écrit sur disque. |
UnpinTime |
Temps consacré à l'écriture des données d'un bloc sur disque lorsque celui-ci n'est plus nécessaire ou lorsque l'opérateur actuel subit une forte pression mémoire. |
OLAP_SCAN_NODE
OLAP_SCAN_NODE gère les tâches de balayage des données. Il crée un ou plusieurs scanners OLAP, chacun étant responsable du balayage d'une partie des données. Le profil s'organise en trois couches reflétant la hiérarchie des appels : OLAP_SCAN_NODE -> OlapScanner -> SegmentIterator.
Certaines ou toutes les conditions de prédicat sont transmises à OLAP_SCAN_NODE. Les conditions pouvant exploiter les index du moteur de stockage sont transmises plus loin à ce dernier pour filtrage ; les autres sont évaluées directement dans OLAP_SCAN_NODE.
Certaines valeurs de métriques varient selon le format de stockage (V1 ou V2).
L'exemple suivant illustre un profil OLAP_SCAN_NODE typique :
OLAP_SCAN_NODE (id=0):(Active: 1.2ms, % non-child: 0.00%)
- BytesRead: 265.00 B # Size of data read from data files. For example, 10 x 32-bit integers = 40 bytes. This reflects data fully loaded into memory, not raw I/O size.
- NumDiskAccess: 1 # Number of disks accessed by the ScanNode.
- NumScanners: 20 # Number of scanners created by the ScanNode.
- PeakMemoryUsage: 0.00 # Peak memory usage during the query.
- RowsRead: 7 # Rows returned from the storage engine to the scanner, excluding rows filtered by the scanner.
- RowsReturned: 7 # Rows returned from the ScanNode to the parent node.
- RowsReturnedRate: 6.979K /sec # RowsReturned / ActiveTime.
- TabletCount: 20 # Number of tablets accessed by the ScanNode.
- TotalReadThroughput: 74.70 KB/sec # BytesRead divided by total execution time. For I/O-bound queries, this approaches total disk throughput.
- ScannerBatchWaitTime: 426.886us # Time for the transfer thread to wait for the scanner thread to return RowBatch data.
- ScannerWorkerWaitTime: 17.745us # Time for the scanner thread to wait for available worker threads in the thread pool.
OlapScanner:
- BlockConvertTime: 8.941us # Time to convert a vectorized block to a row-structured RowBlock. The vectorized block is VectorizedRowBatch (V1) or RowBlockV2 (V2).
- BlockFetchTime: 468.974us # Time for the rowset reader to get blocks.
- ReaderInitTime: 5.475ms # Time for the OLAP scanner to initialize readers. Includes MergeHeap creation time (V1) and the time to generate all iterator levels and read the first block group (V2).
- RowsDelFiltered: 0 # Rows filtered based on DELETE information in the tablet and rows marked for deletion in the Unique Key model.
- RowsPushedCondFiltered: 0 # Rows filtered by predicates pushed down from a join operation (e.g., from BuildTable to ProbeTable). This value is approximate; filtering may be skipped if the effect is poor.
- ScanTime: 39.24us # Time for data to travel from ScanNode to the parent node.
- ShowHintsTime_V1: 0ns # V1 only: time to read some data for ScanRange splitting.
SegmentIterator:
- BitmapIndexFilterTimer: 779ns # Time to filter data using bitmap indexes.
- BlockLoadTime: 415.925us # Time for the segment reader (V1) or segment iterator (V2) to get blocks.
- BlockSeekCount: 12 # Number of block seeks during segment reading.
- BlockSeekTime: 222.556us # Time consumed for block seeks during segment reading.
- BlocksLoad: 6 # Number of blocks read.
- CachedPagesNum: 30 # V2 only: number of pages that hit the page cache.
- CompressedBytesRead: 0.00 # V1: size of data before decompression read from file. V2: size of pages before compression that did not hit the page cache.
- DecompressorTimer: 0ns # Time consumed for data decompression.
- IOTimer: 0ns # Actual I/O time for reading data from the operating system.
- IndexLoadTime_V1: 0ns # V1 only: time to read index streams.
- NumSegmentFiltered: 0 # Number of segments completely filtered out based on column statistics and query conditions.
- NumSegmentTotal: 6 # Total number of segments involved in the query.
- RawRowsRead: 7 # Source data rows read from the storage engine after all preceding filtering.
- RowsBitmapIndexFiltered: 0 # V2 only: rows filtered using bitmap indexes.
- RowsBloomFilterFiltered: 0 # V2 only: rows filtered using BloomFilter indexes.
- RowsKeyRangeFiltered: 0 # V2 only: rows filtered using SortkeyIndex indexes.
- RowsStatsFiltered: 0 # V2: rows filtered using ZoneMap indexes, including delete conditions. V1: includes rows filtered using BloomFilter indexes.
- RowsConditionsFiltered: 0 # V2 only: rows filtered by all column indexes combined.
- RowsVectorPredFiltered: 0 # Rows filtered by vectorized condition operations.
- TotalPagesNum: 30 # V2 only: total number of pages read.
- UncompressedBytesRead: 0.00 # V1: size of data after decompression (or file size if not compressed). V2: size of pages that did not hit the page cache after decompression (or page size if not compressed).
- VectorPredEvalTime: 0ns # Time to perform filtering by vectorized condition.
- ShortPredEvalTime: 0ns # Time to perform filtering by short-circuit predicate.
- PredColumnReadTime: 0ns # Time consumed for predicate column reading.
- LazyReadTime: 0ns # Time consumed to read non-predicate columns.
- OutputColumnTime: 0ns # Time consumed for column materialization.
Relations entre les métriques de filtrage
Les métriques de comptage de lignes d'un profil OLAP_SCAN_NODE révèlent l'efficacité avec laquelle les prédicats et les index réduisent le volume de données à chaque étape. Ce qui suit décrit la séquence de filtrage au format V2. Les métriques du format V1 ont des significations légèrement différentes.
Phase d'initialisation
Le filtrage s'effectue dans l'ordre suivant :
SortkeyIndex — Si la requête comporte des plages de clés (plages de clés préfixées), les données sont filtrées en premier. Les lignes éliminées sont comptabilisées dans
RowsKeyRangeFiltered.Index Bitmap — Un filtrage précis par colonne est appliqué pour les conditions correspondant aux index bitmap. Les lignes éliminées sont comptabilisées dans
RowsBitmapIndexFiltered.-
Index BloomFilter — Les conditions d'égalité (
=,IN,IS) sont filtrées à l'aide des index BloomFilter. Les lignes éliminées sont comptabilisées dansRowsBloomFilterFiltered.RemarqueRowsBloomFilterFiltered
est calculé comme le nombre total de lignes du segment moins les lignes restantes après le filtrage BloomFilter. Un chevauchement avec les lignes déjà éliminées par les index bitmap est possible.
Index ZoneMap — Les données sont filtrées selon les conditions de requête et de suppression. Les lignes éliminées sont comptabilisées dans
RowsStatsFiltered.RowsConditionsFilteredcorrespond au total des lignes filtrées par l'ensemble des index combinés, y comprisRowsBloomFilterFilteredetRowsStatsFiltered.
Phase suivante
Après l'initialisation, les données restantes passent par plusieurs étapes supplémentaires :
RowsDelFiltered: Lignes éliminées par les conditions de suppression. Elles sont également comptabilisées dansRowsStatsFiltered.RawRowsRead: Lignes restantes après tous les filtrages précédents.RowsRead: Lignes renvoyées par le moteur de stockage au scanner. Cette valeur est généralement inférieure àRawRowsReadcar le moteur de stockage peut agréger des lignes. Un écart important entreRawRowsReadetRowsReadsignale une agrégation intensive, ce qui peut impacter les performances.RowsReturned: Lignes finalement renvoyées par ScanNode au nœud parent. Cette valeur est généralement inférieure àRowsReadcar les prédicats non transmis au moteur de stockage sont appliqués au niveau du scanner. Un écart important entreRowsReadetRowsReturnedsignifie que de nombreux prédicats à haute sélectivité n'atteignent pas le moteur de stockage, où le filtrage serait pourtant plus efficace.
Prises ensemble, les métriques Rows***Filtered permettent d'évaluer si les prédicats de requête sont bien transmis au moteur de stockage et de mesurer l'efficacité de chaque type d'index.
Autres métriques
-
Les métriques situées sous
OlapScanner— telles queIOTimeretBlockFetchTime— sont cumulatives sur l'ensemble des threads du scanner. Comme ces threads lisent les données de manière asynchrone, ces valeurs accumulées reflètent le temps de travail total des scanners, et non le temps horloge murale du ScanNode. Le pourcentageActiveenregistre la proportion réelle du temps pendant lequel ScanNode a contribué au plan d'exécution global. Il est normal d'observer unIOTimerde plusieurs dizaines de secondes alors queActivene dépasse pas quelques secondes, pour deux raisons :IOTimercumule le temps de nombreux scanners fonctionnant en parallèle.Si le nœud parent est lent (par exemple 100 secondes), ScanNode (10 secondes) termine rapidement et prépare les données en arrière-plan. Le parent récupère ensuite les données préparées, ce qui explique pourquoi le temps
Activede ScanNode est court.
NumScannerscorrespond au nombre de tâches soumises par le scanner au pool de threads, géré parRuntimeState. Les paramètresdoris_scanner_thread_pool_thread_numetdoris_scanner_thread_pool_queue_sizecontrôlent respectivement la taille du pool de threads et la longueur de la file d'attente. Un nombre de threads excessif ou insuffisant affecte l'efficacité de la requête. Vous pouvez également diviser certaines métriques par le nombre de threads pour estimer approximativement le temps consommé par chaque thread.TabletCountindique le nombre de tablettes à balayer. Un nombre élevé implique davantage de lectures aléatoires et d'opérations de fusion de données.UncompressedBytesReadreflète le volume de données lu. Une valeur élevée peut indiquer une charge E/S importante.Comparez
CachedPagesNumàTotalPagesNumpour évaluer le taux de réussite du cache de pages. Un taux plus élevé réduit à la fois les E/S et la surcharge de décompression.
Buffer pool
| Paramètre | Description |
|---|---|
AllocTime |
Temps consacré à l'allocation mémoire. |
CumulativeAllocationBytes |
Taille cumulée de la mémoire allouée. |
CumulativeAllocations |
Nombre cumulé d'allocations mémoire. |
PeakReservation |
Taille maximale de réservation. |
PeakUnpinnedBytes |
Taille des données mémoire non épinglées (unpinned). |
PeakUsedReservation |
Utilisation mémoire des réservations. |
ReservationLimit |
Limite de réservation dans le buffer pool. |