Article
· Mai 9 9m de lecture

Traitement parallèle des requêtes - ( au niveau du système et en fonction des requêtes)

L'indication de requête parallèle augmente les performances de certaines requêtes sur les systèmes multiprocesseurs par le biais du traitement parallèle. L'optimiseur SQL détermine les cas où cela est bénéfique. Sur les systèmes à un seul processeur, cette indication n'a aucun effet.

Le traitement parallèle peut être géré par:

  1. Définition de l'option auto parallel pour l'ensemble du système.
  2. L'utilisation du mot-clé %PARALLEL dans la clause FROM de certaines requêtes.

Le mot clé %PARALLEL est ignoré lorsqu'il est appliqué aux requêtes suivantes:

  1. Les requêtes INSERT, UPDATE et DELETE (cette fonctionnalité ne s'applique qu'aux requêtes SELECT)
  2. Les requêtes impliquant des fonctions ou des variables spécifiques au processus
  3. Une sous-requête corrélée à une requête englobante.
  4. Une sous-requête contenant des prédicats complexes, tels que les prédicats FOR SOME et FOR SOME %ELEMENT.

En plus des raisons mentionnées précédemment, voici quelques raisons pour lesquelles le traitement parallèle des requêtes peut être ignoré:

  • Certaines requêtes complexes ne bénéficient pas d'un traitement parallèle, même si elles semblent en bénéficier au départ.
  • Certaines configurations et paramètres de base de données ne supportent pas le traitement %PARALLEL.
  • Les dépendances et les relations au sein de la structure des données peuvent empêcher une parallélisation efficace.

Dans des scénarios suivants, %PARALLEL n'effectuera pas de traitement parallèle:

  1. La requête inclut à la fois les clauses TOP et ORDER BY, en optimisant le temps le plus rapide pour atteindre la première ligne.
  2. La requête fait référence à une vue et renvoie un identifiant de vue.
  3. La requête utilise des formats de stockage personnalisés ou des tables GLOBAL TEMPORARY ainsi que des tables avec un stockage de référence global étendu.
  4. La requête accède à une table avec une sécurité au niveau de la ligne.
  5. Les données sont stockées dans une base de données distante.
  6. La collation NLS au niveau du processus ne correspond pas à la collation NLS de tous les globaux impliqués.

Pour plus de détails sur les options, les considérations et les restrictions, reportez-vous à Configure Parallel Query Processing (Interystems Documentation) et Specify Optimization Hints in Queries (Configuration du traitement parallèle des requêtes (Documentation Interystems) et Spécifier les conseils d'optimisation dans les requêtes). Ce sujet a été récemment exploré dans le cadre d'une discussion au sein de la Communauté de développeurs d'InterSystems (DC), qui a inspiré cet article sur IRIS, Cache et Ensemble.

InterSystems IRIS supporte le traitement parallèle à la fois pour le SQL intégré, le SQL dynamique et le SQL dans les QueryMethods. Lorsque le mot-clé %PARALLEL est utilisé dans la clause FROM d'une requête pour suggérer un traitement parallèle. L'optimiseur SQL déterminera si la requête peut bénéficier d'un traitement parallèle et l'appliquera le cas échéant.

Pour utiliser efficacement le traitement %PARALLEL dans InterSystems IRIS, plusieurs paramètres et restrictions doivent être pris en compte, tant au niveau du système qu'au niveau de la requête, afin d'en tirer tous les avantages.

Dans le cas où vous essayez d'obtenir le traitement %PARALLEL à l'aide du traitement parallèle des requêtes à l'échelle du système et que le mode adaptatif est désactivé, vous pouvez activer le traitement parallèle des requêtes à l'échelle du système via le Portail de gestion ou $SYSTEM.SQL.Util.SetOption()
Exemple

USER>w ##class(%SYSTEM.SQL.Util).GetOption("AutoParallel")
0
USER>d ##class(%SYSTEM.SQL.Util).SetOption("AutoParallel",1,.oldParVal)

USER>w ##class(%SYSTEM.SQL.Util).GetOption("AutoParallel")
1
USER>zw oldParVal
oldParVal=0

Autres aspects importants à prendre en compte lors de la mise en œuvre de la fonctionnalité %PARALLEL.

  • Lorsque le AdaptiveMode est activé, le traitement parallèle automatique est appliqué à toutes les requêtes SELECT, en les accompagnant de la mention %PARALLEL. Cependant, toutes les requêtes ne peuvent pas utiliser le traitement parallèle, car l'optimiseur SQL peut en décider autrement.
  • Lorsque nous essayons d'utiliser cette fonctionnalité %PARALLEL, nous devons également prendre en compte le paramètre AutoParallelThreshold (la valeur par défaut est 3200) et ce paramètre n'est pas utile dans le cas où AutoParallel est désactivé.
  • Le paramètre AutoParallelThreshold détermine si une requête est exécutée en parallèle, les valeurs les plus élevées réduisant les chances de traitement en parallèle. La valeur par défaut est 3200, elle peut être ajustée via $SYSTEM.SQL.Util.SetOption("AutoParallelThreshold",n,.oldval).
  • Dans les environnements partagés, le traitement parallèle est utilisé pour toutes les requêtes, quel que soit le seuil, lorsque le mode adaptatif AdaptiveMode est activé.
  • Lorsque le mode AdaptiveMode est activé (défini à 1) et que la fonctionnalité AutoParallel est désactivée, le Mode adaptatif remplace le paramètre AutoParallel et active le traitement parallèle.

Exemple:
Exemple de classe avec 100 000 enregistrements remplis

 Class SQLClass.MyTest Extends (%Persistent, %Populate)
  {

    Property Name As %String(MAXLEN = 255);

    Property Age As %Integer(MAXVAL = 100, MINVAL = 1);

    Property Address As %String(MAXLEN = 255);

    Property City As %String(MAXLEN = 255);

    Property State As %String(MAXLEN = 255);

    Property Zip As %String(MAXLEN = 255);

    Property Country As %String(MAXLEN = 255);

    Property Comment As %String(MAXLEN = 255);

    Property Hobby As %String(MAXLEN = 255);

    Property JobTitle As %String(MAXLEN = 255);

    Property Company As %String(MAXLEN = 255);

    Property PhoneNumber As %String(MAXLEN = 255);

    Property Email As %String(MAXLEN = 255);

    Property Gender As %String(MAXLEN = 1);

    Property Ethnicity As %String(MAXLEN = 255);

    Property Race As %String(MAXLEN = 255);

    Property Religion As %String(MAXLEN = 255);

    Property MaritalStatus As %String(MAXLEN = 255);

    Property Children As %Integer(MAXVAL = 10, MINVAL = 0);

    Property Income As %Integer(MAXVAL = 100000, MINVAL = 0);

    Property Occupation As %String(MAXLEN = 255);

    Property Education As %String(MAXLEN = 255);

    Property HomePhone As %String(MAXLEN = 255);

    Property MobilePhone As %String(MAXLEN = 255);

    Property WorkPhone As %String(MAXLEN = 255);

    Property WorkEmail As %String(MAXLEN = 255);

    Property HomeEmail As %String(MAXLEN = 255);

    Property HomeAddress As %String(MAXLEN = 255);

    Property HomeCity As %String(MAXLEN = 255);

    Property HomeState As %String(MAXLEN = 255);

    Property HomeZip As %String(MAXLEN = 255);

    Property HomeCountry As %String(MAXLEN = 255);

    Property WorkAddress As %String(MAXLEN = 255);

    Property WorkCity As %String(MAXLEN = 255);

    Property WorkState As %String(MAXLEN = 255);

    Property WorkZip As %String(MAXLEN = 255);

    Property WorkCountry As %String(MAXLEN = 255);

    Property WorkPhoneNumber As %String(MAXLEN = 255);

    Property WorkMobilePhone As %String(MAXLEN = 255);

    Property WorkFax As %String(MAXLEN = 255);

    Property WorkWebsite As %String(MAXLEN = 255);

    Property WorkComments As %String(MAXLEN = 255);


    Index IdxAge On Age;
}

Test n° 1
Exemple d'exécution sans % PARALLEL (pour afficher 10 000 enregistrements en SMP)

select * from SQLClass.MyTest where age>40
  • 3.2069 secondes
  • 10404 références globales
  • 3325407 commandes exécutées

Exemple d'exécution avec %PARALLEL(pour afficher 10 000 enregistrements dans SMP)

select * from %PARALLEL SQLClass.MyTest where age>40
  • 2.8681 secondes
  • 10404 références globales
  • 3325407 commandes exécutées

Test n° 2 :
Exemple d'exécution sans % PARALLEL (pour afficher 1 enregistrement en SMP)

select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10
  • 0.4037 secondes
  • 46559 références globales
  • 1459936 commandes exécutées

Exemple d'exécution avec %PARALLEL (pour afficher 1 enregistrement en SMP)

select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from %PARALLEL SQLClass.MyTest where age>10
  • 0.0845 secondes
  • 46560 références globales
  • 1460418 commandes exécutées

Exemple avec SQL intégré

ClassMethod embeddedSQL() As %Status
{
    // w ##Class(SQLClass.MyTest).embeddedSQL()
    Set sc = $$$OK
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2)
    &sql(select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10)
    w:'SQLCODE "Without %Parallel : ",($p($zts,",",2)-stime),!
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2)
    &sql(select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from %PARALLEL SQLClass.MyTest where age>10)
    w:'SQLCODE "With %Parallel : ",($p($zts,",",2)-stime),!
    Return sc
}

Résultats (SQL intégré) :
USER> D ##Class(SQLClass.MyTest).embeddedSQL()
5466 blocs supprimés
Sans %Parallel : .355737
5217 blocs supprimés
Avec %Parallel : .3407056

USER>

Exemple avec SQL dynamique

ClassMethod dynamicSQL() As %Status
{
     // w ##Class(SQLClass.MyTest).dynamicSQL()
    Set sc = $$$OK
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2), recCnt=0
    Set rs=##class(%ResultSet).%New()
    Set sc=rs.Prepare("select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10")
    Set sc=rs.Execute()
    While(rs.Next()) {
        w "COUNT(Children) : ",rs.GetData(1),"; MAX(Children) : ",rs.GetData(2),"; MIN(Children) : ",rs.GetData(3),"; AVG(Children) : ",rs.GetData(4),!
    }
    w "Without %Parallel : ",($p($zts,",",2)-stime),!!!
    DO ClearBuffers^|"%SYS"|GLOBUFF()
    set stime=$p($zts,",",2), recCnt=0
    Set sc=rs.Prepare("select COUNT(Children),MAX(Children),MIN(Children),AVG(Children) from SQLClass.MyTest where age>10")
    Set sc=rs.Execute()
    While(rs.Next()) {
        w "COUNT(Children) : ",rs.GetData(1),"; MAX(Children) : ",rs.GetData(2),"; MIN(Children) : ",rs.GetData(3),"; AVG(Children) : ",rs.GetData(4),!
    }
    w "With %Parallel : ",($p($zts,",",2)-stime),!
    Return sc
}

Résultats (SQL dynamique):
USER>d ##Class(SQLClass.MyTest).dynamicSQL()
22163 blocs supprimés
NOMBRE(Enfants) : 89908; MAX(Enfants) : 10; MIN(Enfants) : 0; AVG(Enfants) : 5.021989144458780086
Sans %Parallel : .4036913

5721 blocs supprimés
NOMBRE(Enfants) : 89908; MAX(Enfants) : 10; MIN(Enfants) : 0; AVG(Enfants) : 5.021989144458780086
Avec %Parallel : .3693442

Discussion (0)2
Connectez-vous ou inscrivez-vous pour continuer