Tous les produits
Search
Centre de documentation

Lindorm:FAQ Lindorm SQL

Dernière mise à jour :Aug 11, 2026

Problèmes courants et solutions liés à l'utilisation de Lindorm SQL avec LindormTable (moteur de table large).

Remarque

Les problèmes abordés dans cette rubrique s'appliquent uniquement à LindormTable.

Problèmes de requête

  • Q : Comment résoudre ou éviter les requêtes inefficaces ?

    R : Si votre requête renvoie l'erreur This query may be a full table scan and thus may have unpredictable performance, elle est considérée comme inefficace.

    Qu'est-ce qu'une requête inefficace ? Sur LindormTable, une requête dont les conditions de filtrage ne peuvent pas exploiter efficacement la clé primaire ou un index existant impose un balayage complet de la table. De telles requêtes sont jugées inefficaces. LindormTable les bloque par défaut afin de préserver les performances et la stabilité de la base de données.

    Les règles de correspondance suivent la règle du préfixe gauche, identique à celle utilisée par MySQL pour les index composites. Le système fait correspondre les colonnes de votre clause WHERE aux colonnes de la clé primaire (ou de la clé d'index) en commençant par la colonne la plus à gauche. Si votre requête ignore la première colonne, la clé n'est pas utilisée et un balayage complet de la table en résulte.

    Par exemple, si la table test possède une clé primaire composite (p1, p2, p3) et que vous exécutez :

    SELECT * FROM test WHERE p2 < 30;

    La requête ignore p1 ; LindormTable ne peut donc pas utiliser la clé primaire. La totalité de la table est analysée pour satisfaire la condition p2 < 30.

    Pour corriger ou éviter ce problème :

    • Incluez la première colonne de la clé primaire dans la clause WHERE, en respectant la règle du préfixe gauche.

    • Repensez la conception de la clé primaire de la table. Consultez la rubrique Conception d'une clé primaire pour une table large.

    • Créez un index secondaire sur les colonnes interrogées. Consultez la rubrique Index secondaires.

    • Pour les requêtes multidimensionnelles portant sur plusieurs colonnes, créez un index de recherche. Consultez la rubrique Index de recherche.

    • Pour forcer l'exécution de la requête inefficace, ajoutez l'indicateur /*+ _l_allow_filtering_ */ :

      SELECT /*+ _l_allow_filtering_ */ * FROM dt WHERE nonPK = 100;
    Important

    Forcer un balayage complet de la table risque de dégrader les performances globales et la stabilité de la base de données. N'utilisez cette approche qu'après avoir évalué son impact.

  • Q : Pourquoi une requête GROUP BY échoue-t-elle avec une erreur « subPlan groupby keys » ?

    R : Message d'erreur :

    The diff group keys of subPlan is over lindorm.aggregate.subplan.groupby.keys.limit=..., it may cost a lot memory so we shutdown this SubPlan

    L'opération GROUP BY a généré trop de groupes. Un nombre élevé de groupes consomme une quantité excessive de mémoire et augmente la charge de l'instance ; LindormTable interrompt alors le sous-plan.

    Pour résoudre ce problème :

    • Ajoutez des conditions de filtrage pour réduire le nombre de groupes avant l'agrégation.

    • Pour les scénarios d'agrégation multidimensionnelle, créez un index de recherche afin de déporter la charge de travail. Consultez la rubrique Index de recherche.

    • Pour augmenter le seuil maximal de groupes, contactez le support technique Lindorm (ID DingTalk : s0s3eg3).

    Important

    L'augmentation du seuil de groupes accroît la consommation de mémoire et peut affecter la stabilité de l'instance. Évaluez l'impact avant d'effectuer toute modification.

  • **Q : Pourquoi SELECT * sur une table à colonnes dynamiques échoue-t-il avec une erreur « Limit not set » ?**

    R : Message d'erreur :

    Limit of this select statement is not set or exceeds config when select all columns from table with property DYNAMIC_COLUMNS=true

    Les tables dotées de colonnes dynamiques n'ont pas de schéma fixe et peuvent contenir un grand nombre de colonnes, imprévisible. L'exécution de SELECT * sans limite de lignes entraîne des entrées/sorties élevées et augmente la charge de l'instance ; LindormTable exige donc une clause LIMIT pour ce type de requêtes.

    Ajoutez une clause LIMIT à l'instruction SELECT :

    SELECT * FROM test LIMIT 10;
  • Q : Pourquoi une requête échoue-t-elle avec l'erreur « Code grows beyond 64 KB » ?

    R : Le moteur SQL de Lindorm utilise la compilation Just-In-Time (JIT) : il génère du bytecode à partir du plan physique de la requête et le compile au moment de l'exécution. Cette erreur signifie que le bytecode d'une méthode générée dépasse la limite de 64 Ko imposée par la machine virtuelle Java (JVM).

    La cause la plus fréquente réside dans un prédicat de l'instruction SQL trop long ou trop complexe, produisant un bytecode trop volumineux pour être exécuté.

    Simplifiez les expressions de prédicat dans l'instruction SQL. Décomposez les conditions complexes en éléments plus petits ou réécrivez la logique afin de réduire la taille du bytecode.

  • Q : Pourquoi une requête échoue-t-elle avec l'erreur « The estimated memory used by the query exceeds the maximum limit » ?

    R : Le moteur SQL consomme une quantité importante de mémoire lors du traitement des jeux de résultats — durant l'agrégation, le tri ou la déduplication. Comme Lindorm SQL est conçu pour des charges de travail en ligne à forte concurrence, il limite chaque requête à 8 Mo de mémoire par défaut. Le dépassement de cette limite déclenche une exception de débordement de mémoire.

    Étape 1 — Diagnostiquer avant d'agir :

    Examinez le plan d'exécution pour déterminer si les opérateurs d'agrégation et de tri sont poussés vers le moteur de stockage ou exécutés dans le moteur SQL. Consultez la rubrique Interprétation d'un plan d'exécution.

    • Si des opérateurs lourds s'exécutent dans le moteur SQL, l'optimisation de la requête constitue la solution appropriée (voir Option 1).

    • Si les opérateurs sont déjà poussés et que la requête est optimisée, augmentez la limite de mémoire (voir Option 2).

    Option 1 — Optimiser la requête (recommandé) :

    Poussez l'agrégation et le tri vers le moteur de stockage en utilisant des index, et renforcez les conditions de filtrage pour réduire la quantité de données traitées par le moteur SQL.

    Option 2 — Augmenter la limite de mémoire :

    Si la requête est déjà optimisée et que vous avez besoin d'une limite plus élevée, ajustez QUERY_MAX_MEM à l'aide de ALTER SYSTEM :

    ALTER SYSTEM SET QUERY_MAX_MEM = 8388608;

    Vérifiez la valeur actuelle avec l'instruction SHOW VARIABLES.

    Si la version du moteur SQL est antérieure à 2.9.6.0, contactez le support technique Lindorm (ID DingTalk : s0s3eg3) pour augmenter la limite.

    Important

    Dans les environnements à forte concurrence, l'augmentation de QUERY_MAX_MEM accroît la pression mémoire sur le cluster et peut déclencher un Full GC forcé, réduisant la réactivité de l'ensemble du cluster. Évaluez attentivement le débit des requêtes et le niveau de concurrence avant d'augmenter cette valeur.

  • **Q : Pourquoi est-il déconseillé d'utiliser de nombreuses conditions IS NULL dans une seule clause WHERE ?**

    R : Sur LindormTable, IS NULL doit gérer à la fois « la colonne existe avec une valeur NULL » et « la colonne n'existe pas ou n'a jamais été écrite ». Lorsqu'une instruction SQL contient plusieurs prédicats IS NULL, le moteur SQL peut développer ces conditions en combinaisons lors de la compilation. N prédicats IS NULL peuvent théoriquement produire jusqu'à 2^N branches, ce qui augmente considérablement le temps de compilation et l'utilisation de la mémoire. Dans les cas graves, cela peut affecter l'exécution des requêtes et la stabilité de l'instance.

    Recommandation : Évitez de combiner de nombreuses conditions column IS NULL dans une seule instruction SELECT, UPDATE ou DELETE. Envisagez les approches suivantes :

    • Réduisez autant que possible la plage de requête en utilisant des clés primaires, des index secondaires ou des index de recherche.

    • Si votre logique métier vérifie fréquemment si des champs sont vides ou présents, exprimez cet état métier explicitement côté écriture — par exemple, avec des valeurs par défaut ou des colonnes de statut.

    • Pour le traitement par lots, divisez le travail en plusieurs instructions SQL aux conditions plus simples, ou récupérez d'abord les clés primaires complètes et traitez-les par lots selon la clé primaire.

  • Q : Pourquoi est-il déconseillé d'utiliser de nombreux groupes OR combinés avec AND dans une clause WHERE ?

    Problème : Une instruction SQL dont la clause WHERE relie plusieurs groupes OR entre parenthèses avec AND, par exemple :

    SELECT * FROM orders
    WHERE (status = 1 OR status = 2)
      AND (pay_type = 'wechat' OR pay_type = 'alipay')
      AND (region = 'CN' OR region = 'US')
      AND ...;

    Plus l'imbrication est profonde, plus le risque est élevé. Cela s'applique aussi bien aux instructions SELECT, UPDATE qu'aux instructions DELETE.

    R : Avant d'exécuter une requête, l'optimiseur doit convertir la clause WHERE en forme normale disjonctive (DNF) — un ensemble OR de conditions AND — afin de sélectionner le chemin d'accès optimal par index pour chaque condition indépendante. Lorsque l'optimiseur rencontre (A OR B) AND (C OR D), il doit appliquer la loi distributive pour la développer :

    (A∨B)∧(C∨D) ⇒ (A∧C)∨(A∧D)∨(B∧C)∨(B∧D)

    (A or B) and (C or D) ⇒ (A and C) or (A and D) or (B and C) or (B and D)

    • 2 groupes, chacun avec 2 branches : 2×2 = 4 termes de combinaison.

    • 3 groupes, chacun avec 2 branches : 2×2×2 = 8 termes de combinaison.

    À mesure que le nombre de groupes et de branches par groupe augmente, le nombre de termes de combinaison croît de manière exponentielle. Cela peut augmenter considérablement le temps de compilation de l'optimiseur et l'utilisation de la mémoire, et dans les cas graves, affecter l'exécution des requêtes et la stabilité de l'instance.

    Recommandation :

    • Évitez de combiner de nombreux groupes OR entre parenthèses avec AND dans une seule instruction SQL.

    • Réécrivez les conditions OR portant sur la même colonne avec IN — par exemple, status IN (1, 2) — afin de réduire le nombre de branches développées.

    • Réduisez autant que possible la plage de requête en utilisant des clés primaires, des index secondaires ou des index de recherche.

    • Pour les scénarios de mise en correspondance multidimensionnelle, utilisez un index de recherche. Consultez la rubrique Index de recherche.

    • Si la logique métier impose des conditions complexes, divisez le travail en plusieurs instructions SQL plus simples, ou récupérez d'abord les clés primaires complètes et traitez-les par lots selon la clé primaire.

  • Q : Comment diagnostiquer et résoudre une erreur de limite de mémoire pour une requête spécifique ?

    R : Lorsqu'une requête échoue avec l'erreur de limite de mémoire, suivez ces étapes pour diagnostiquer la cause racine et choisir la solution appropriée :

    Étape 1 — Vérifier le plan d'exécution :

    Exécutez EXPLAIN sur la requête ayant échoué pour afficher son plan d'exécution. Consultez la rubrique Interprétation d'un plan d'exécution pour plus de détails.

    Dans le plan d'exécution, identifiez si les opérateurs gourmands en mémoire — tels que l'agrégation, le tri et la déduplication — s'exécutent dans le moteur SQL ou sont poussés vers le moteur de stockage. Les opérateurs exécutés dans le moteur SQL consomment de la mémoire issue de la limite par requête, tandis que les opérateurs poussés utilisent les ressources du moteur de stockage.

    Étape 2 — Tenter d'optimiser la requête :

    Si des opérateurs gourmands en mémoire s'exécutent dans le moteur SQL, essayez les approches suivantes pour réduire la consommation de mémoire :

    • Pour les opérateurs d'agrégation (GROUP BY, COUNT, SUM, AVG) : Créez un index secondaire ou un index de recherche sur les colonnes regroupées ou agrégées afin de permettre le pushdown des opérateurs vers le moteur de stockage.

    • Pour les opérateurs de tri (ORDER BY) : Assurez-vous que les colonnes de tri correspondent à un index existant pour éviter le tri en mémoire. Vous pouvez également ajouter des conditions WHERE plus strictes pour réduire la taille de l'ensemble de données avant le tri.

    • Pour les opérateurs de déduplication (DISTINCT) : Utilisez un index de recherche pour les requêtes sur des colonnes à cardinalité élevée, ou ajoutez des conditions de filtrage sélectives pour réduire le nombre de lignes traitées.

    Étape 3 — Augmenter la limite de mémoire si nécessaire :

    Si tous les opérateurs sont déjà poussés et que la requête ne peut pas être optimisée davantage, augmentez la valeur de QUERY_MAX_MEM à l'aide de ALTER SYSTEM :

    ALTER SYSTEM SET QUERY_MAX_MEM = <new_value_in_bytes>;

    Vérifiez la valeur actuelle avec l'instruction SHOW VARIABLES.

    Important

    Dans les environnements à forte concurrence, une valeur QUERY_MAX_MEM plus élevée accroît la pression mémoire globale sur le cluster et peut déclencher un Full GC forcé, réduisant la réactivité de l'ensemble du cluster. Évaluez le débit de vos requêtes et le niveau de concurrence avant de modifier cette valeur.

Problèmes d'index et de schéma

  • Q : Pourquoi la création d'un index secondaire échoue-t-elle avec l'erreur « Executing job number exceed, max job number = 8 » ?

    R : Chaque instance Lindorm autorise un maximum de 8 tâches de construction d'index secondaire concurrentes. Si 8 tâches sont déjà en cours d'exécution, les nouvelles tentatives de création d'index échouent.

    Évitez de créer de nombreux index secondaires simultanément. Si vous devez créer un grand nombre d'index en lot, contactez le support technique Lindorm (ID DingTalk : s0s3eg3).

  • Q : Après la suppression d'une colonne, pourquoi le rajout d'une colonne portant le même nom échoue-t-il avec l'erreur « column is under deleting » ?

    R : Après la suppression d'une colonne, LindormTable nettoie de manière asynchrone les données de la colonne de la mémoire, du stockage chaud et du stockage froid. Le système empêche le rajout d'une colonne portant le même nom tant que le nettoyage n'est pas terminé, afin d'éviter les données corrompues dues à des incompatibilités de type ou des collisions de données.

    Le nettoyage s'exécute en arrière-plan et peut prendre beaucoup de temps. Pour l'accélérer, exécutez les instructions suivantes sur la table (remplacez dt par le nom de votre table) :

    -- Flush residual in-memory data to storage.
    ALTER TABLE dt FLUSH;
    
    -- Run compaction to merge and remove deleted data.
    ALTER TABLE dt COMPACT;

    Une fois le nettoyage terminé, rajoutez la colonne.

    Important
    • FLUSH est pris en charge à partir de la version 2.7.1 du moteur SQL. Vérifiez votre version dans le guide des versions SQL.

    • FLUSH et COMPACT sont tous deux asynchrones. L'exécution réussie de l'instruction ne signifie pas que le nettoyage est terminé.

    • L'exécution de COMPACT sur une table contenant un grand volume de données consomme des ressources système importantes. Évitez de l'exécuter pendant les heures de pointe de l'activité.

  • Q : Après la création d'un index secondaire, pourquoi l'écriture de données échoue-t-elle avec une erreur « User-Defined-Timestamp » ?

    R : Message d'erreur :

    Performing put operations with User-Defined-Timestamp in indexed column on MULTABLE_LATEST table is unsupported

    Lorsque vous écrivez des données avec un horodatage personnalisé explicite — par exemple, en utilisant l'indicateur /*+ _l_ts */ dans une instruction UPSERT — la table principale et la table d'index secondaire doivent toutes deux avoir leur mutabilité définie sur MUTABLE_ALL. Cependant, Lindorm définit par défaut les nouvelles tables et index sur MUTABLE_LATEST pour des raisons de performance. L'écriture avec un horodatage personnalisé dans une table d'index ayant la mutabilité MUTABLE_LATEST déclenche cette erreur.

    La propriété MUTABILITY ne peut pas être modifiée après la création d'une table d'index. Vous devez supprimer l'index existant, mettre à jour la mutabilité de la table principale, puis recréer l'index.

    1. Désactivez et supprimez l'index secondaire existant :

      -- Disable the index.
      ALTER INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name> DISABLED;
      
      -- Drop the index.
      DROP INDEX IF EXISTS <original_secondary_index_name> ON <primary_table_name>;

      Consultez la rubrique Suppression d'un index secondaire.

    2. Définissez la mutabilité de la table principale sur MUTABLE_ALL :

      ALTER TABLE IF EXISTS <primary_table_name> SET MUTABILITY='MUTABLE_ALL';
    3. Créez un nouvel index secondaire. Consultez la rubrique CREATE INDEX.

    Remarque

    Pour plus de détails sur l'écriture de données avec un horodatage personnalisé, consultez la rubrique Utilisation des HINTs pour définir des horodatages pour la gestion des données multiversions.

    Remarque

    Pour plus de détails sur l'interaction entre la mutabilité des index secondaires et les horodatages personnalisés, consultez la rubrique Mise à jour d'un index avec un horodatage personnalisé.

Opérations par lots

  • Q : Pourquoi les mises à jour par lots ne sont-elles pas prises en charge, ou pourquoi l'erreur « Update's WHERE clause can only contain PK columns » se produit-elle ?

    R : Seules les mises à jour sur une seule ligne sont prises en charge par défaut. Pour savoir comment activer les mises à jour par lots, consultez la rubrique FAQ sur les opérations par lots.

  • Q : Comment activer les suppressions par lots ?

    R : Pour savoir comment activer et configurer les suppressions par lots, consultez la rubrique FAQ sur les opérations par lots.