Contacts

1s 8 requête de lot. Des requêtes simples. Raisons des performances de requête sous-optimales

Analysons comment la syntaxe des textes des demandes de exemple simple: Document détenu Consommable contenant dans la section tabulaire Des produits liste des articles vendus et quantité. Lors de la réalisation d'un tel document, il est nécessaire d'assurer le contrôle des soldes négatifs stockés dans le registre de cumul des soldes Soldes de marchandises.

La structure de configuration est illustrée sur la figure.

(16,22 kilo-octets) Téléchargements : 64

Formons une requête pour la section tabulaire du document et la table virtuelle les restes registre d'accumulation. Nous prendrons en compte les éventuelles lignes en double dans le document, pour cela nous regrouperons les enregistrements.

Demande = Nouvelle demande ;
Request.Text = "
| CHOISIR
| Doc.Nomenclature,
| SUM (Doc.Quantity) AS Doc_Number,
| MINIMUM (EST NULL (Reg.Quantity, Remaining, 0)) AS Reg_Number
| DE
| Document.Consommable.Marchandises AS Doc
| ARTICULATION GAUCHE
| Registre d'accumulation. Soldes des marchandises. Restes () AS Reg
| AU
| Doc.Nomenclature = Reg.Nomenclature
| O
| Lien = & Lien
| CHARGER PAR Doc.Nomenclature " ;

// Balayez le registre

Fin de cycle ;

Fin de la procédure

Naturellement, la requête donnée n'est absolument pas optimale. A l'aide de requêtes imbriquées, on l'optimise : Regroupons la section tabulaire du document avant de la joindre à la table des résidus, passons la liste des biens aux paramètres de la table virtuelle comme valeur de la condition de calcul des résidus . En conséquence, notre demande prendra la forme suivante :

| CHOISIR
| Doc.Nomenclature,

| DE
| (SÉLECTIONNER

| À PARTIR DE
| Document.Facture.Marchandises
| OÙ
| Lien = & Lien
| CHARGER PAR Nomenclature) AS Doc
| ARTICULATION GAUCHE
Nomenclature B
| (SÉLECTIONNEZ DIVERS
| Nomenclature
| À PARTIR DE
| Document.Facture.Marchandises
| OÙ
| Lien = & Lien)) AS Reg
| AU

Si dans une requête il était nécessaire d'obtenir des données des restes de différents registres, alors la valeur du filtre, et donc notre deuxième sous-requête, serait répétée dans tous les paramètres des tables virtuelles, il est naturel que le système se tourne à nouveau vers la base de données pour récupération de données avec chaque sous-requête.

Tables temporaires

Je ne me souviens pas à partir de quelle version il est devenu possible d'utiliser des tables temporaires dans les requêtes. Pour cela, l'objet "Gestionnaire de tables temporaires" est utilisé. En fait, le gestionnaire de tables temporaires décrit l'espace de noms des tables temporaires et se charge de les créer et de les détruire dans la base de données.

Les tables temporaires elles-mêmes sont en effet physiquement créées dans la base de données, vous devez donc les traiter avec précaution, car le sous-système de disque est actuellement la partie la plus lente de la technologie, et la vitesse de création et de destruction des tables en dépend directement.

Réécrivons la requête pour utiliser des tables temporaires. Placez la section tabulaire regroupée du document et la liste des produits pour le filtre des tables virtuelles dans les tables temporaires :

Procédure de traitement de la comptabilisation (refus, mode de comptabilisation)

MVT = nouveau gestionnaire de tables temporaires ;

Demande = Nouvelle demande ;
Request.Text = "
| CHOISIR
| Nomenclature, SUM (Quantité) AS Quantité
| POST-DOCTEUR
| DE
| Document.Facture.Marchandises
| O
| Lien = & Lien
| CHARGER PAR Nomenclature " ;

Demande = Nouvelle demande ;
Query.TemporaryTablesManager = MVT;
Request.Text = "SÉLECTIONNER DIVERS
| Nomenclature
| PLACER LA LISTE DES ÉLÉMENTS
| DE
| Document.Facture.Marchandises
| O
| Lien = & Lien ";

Demande = Nouvelle demande ;
Query.TemporaryTablesManager = MVT;
Request.Text = "
| CHOISIR
| Doc.Nomenclature,
| Doc.Quantity AS Doc_Number,
| IS NULL (Reg.Amount Remaining, 0) AS Reg_Number
| DE
| DOCTCH AS Doc
| ARTICULATION GAUCHE
| Registre d'accumulation.Soldes des marchandises.Reste (,
| Nomenclature
| À PARTIR DE
| AU
| Doc.Nomenclature = Reg.Nomenclature " ;

QueryResult = Query.Run ();
Selection = QueryResult.Select ();

Tandis que Fetch.Next () boucle

// Vérifier les résidus négatifs

// Balayez le registre

Fin de cycle ;

Fin de la procédure

Lorsque vous utilisez des tables temporaires dans le texte de la requête, utilisez l'instruction Lieu pour créer une nouvelle table temporaire, dans ce cas, le système ne transfère pas le contenu de cette table au résultat de la requête (voir note 1 et exemple 2 dans le texte ci-dessus), mais le nombre d'enregistrements placés dans la table temporaire, si vous le souhaitez, vous ne pouvez pas accepter cette valeur.

Il est également permis d'utiliser l'instruction Détruire dans ce cas, la table temporaire est détruite, sinon les tables temporaires sont détruites avec l'objet gestionnaire de table temporaire.

Dans notre requête principale, j'ai utilisé les noms des tables temporaires comme indication de la source de données (il faut leur attribuer un synonyme, ce que nous voyons dans le texte). Vous pouvez utiliser des tables temporaires comme source plus d'une fois, ce qui, s'il est utilisé habilement, vous permettra de raccourcir le texte de la requête (améliorer la lisibilité des requêtes complexes) et d'augmenter la vitesse (lors de l'utilisation de données de table temporaire à plusieurs endroits dans la requête) .

Demandes par lots

Les requêtes par lots complètent logiquement la fonctionnalité des tables temporaires et offrent plus d'options lorsque vous travaillez avec des requêtes.

Dans une requête batch, en effet, vous pouvez décrire plusieurs requêtes, toutes deux liées entre elles à l'aide de tables temporaires, et non liées (c'est possible, mais on ne sait pas pourquoi ?). En conséquence, vous pouvez exécuter toutes les requêtes de manière séquentielle et accepter comme résultat soit un tableau avec les résultats de chaque exécution de requête, soit le résultat de la dernière. Pour obtenir un tableau avec les résultats de la requête, utilisez la méthode Exécuter le package () requête d'objet, et pour obtenir le résultat de la dernière requête ExécuterRequête ().

Dans le texte de la demande, les demandes de package sont séparées par le ";" (point virgule). Une requête par lots a un espace de noms de table virtuelle. L'utilisation d'un gestionnaire de tables temporaires n'est pas obligatoire, mais c'est possible si vous souhaitez transférer des tables temporaires d'une requête batch à une autre.

Réécrivons la procédure pour utiliser les requêtes batch :

Procédure de traitement de la comptabilisation (refus, mode de comptabilisation)

Demande = Nouvelle demande ;
Request.Text = "
| CHOISIR
| Nomenclature, SUM (Quantité) AS Quantité
| POST-DOCTEUR
| DE
| Document.Facture.Marchandises
| O
| Lien = & Lien
| CHARGER PAR Nomenclature
|;
| SÉLECTIONNER DIVERS
| Nomenclature
| PLACER LA LISTE DES ÉLÉMENTS
| DE
| Document.Facture.Marchandises
| O
| Lien = & Lien
|;
| CHOISIR
| Doc.Nomenclature,
| Doc.Quantity AS Doc_Number,
| IS NULL (Reg.Amount Remaining, 0) AS Reg_Number
| DE
| DOCTCH AS Doc
| ARTICULATION GAUCHE
| Registre d'accumulation.Soldes des marchandises.Reste (,
| Nomenclature B (SÉLECTIONNEZ DIVERS
| Nomenclature
| À PARTIR DE
| Liste d'articles AS Liste d'articles)) AS Reg
| AU
| Doc.Nomenclature = Reg.Nomenclature " ;

Tandis que Fetch.Next () boucle

// Vérifier les résidus négatifs

// Balayez le registre

Fin de cycle ;

Fin de la procédure

En fait, j'ai supprimé la définition de l'objet de requête et l'utilisation du gestionnaire de table temporaire, combiné les textes de la requête (notez le séparateur ";" entre les textes). En conséquence, le texte de la requête est devenu plus lisible (et la lisibilité de la requête est grandement améliorée lors de l'utilisation du concepteur de requêtes).

Après avoir exécuté la requête à la variable Tableau de résultats nous aurons 3 éléments. Les deux premiers contiendront un nombre caractérisant le nombre d'enregistrements placés dans des tables temporaires DOCT et Liste d'objets, et le troisième contiendra une sélection avec des champs Nomenclature, Doc_ Quantité et Reg_ Quantité.

Dans une variable Résultat de la demande seul l'échantillon sera inclus.

Eh bien, c'est à peu près tout pour les demandes par lots. Un mécanisme très pratique tant du point de vue de l'écriture de requêtes que du point de vue de la lecture de requêtes complexes.

La plateforme 1C Enterprise vous permet d'exécuter plusieurs requêtes séquentiellement à la fois. En 1C, cela s'appelle un lot de requêtes. Au sein d'un même package, chaque demande est séparée par un point-virgule.

Pour réaliser une exécution étape par étape des requêtes dans un package, en règle générale, des tables temporaires sont initialement créées, puis des conditions pour leur utilisation conjointe sont formées, telles que des filtres, des jointures, des jointures. Grâce à cela, le résultat final est atteint. Les tables temporaires obtenues à la suite de toute requête dans le package continuent d'exister jusqu'à la fin de l'intégralité du package ou jusqu'à ce qu'une requête soit exécutée qui détruit les tables temporaires.

De plus, l'utilisation de requêtes par lots et de tables temporaires augmente considérablement la lisibilité de l'intégralité de ce code. Les requêtes complexes qui contiennent également des requêtes imbriquées peuvent être très difficiles à comprendre. Cependant, si vous divisez une longue requête complexe en plusieurs et utilisez même des tables temporaires, cela améliorera non seulement la perception, mais dans la plupart des cas, vous obtiendrez de meilleures performances.

Un autre détail important en faveur des requêtes par lots dans 1C est que, contrairement, nous pouvons obtenir le résultat de chaque requête dans un lot séparément.

Un exemple de création d'un package de requêtes en langage 1C

Pour voir un exemple de création d'un package de requête, nous utiliserons le constructeur de requête, que nous appellerons pour plus de clarté à partir de la console de requête. Ainsi, nous pouvons immédiatement voir le résultat de l'exécution du package.

Créons une simple requête batch. Je propose d'insérer immédiatement le texte de la demande dans, puis d'ouvrir et de voir comment le package de demande est formé. Ajoutez une nouvelle requête à la console et collez le texte suivant :

Obtenez gratuitement 267 didacticiels vidéo 1C :

Lien autoportant,
Parent autonome,
Code autoportant,
Autoportant.Code QuickSelection,
Autoportant.
Type autoportant,
Autonome, hors bilan,
Autonome, quantitatif,
À PARTIR DE
Plan de comptes.

Autosuffisant.Ref = & Compte
;
////////////////////////////////////////////////////////////////////////////////

SÉLECTIONNER
Types autoportants
Types autoportants
Types de sous-konto autoportants Type de sous-konto.
Types autoportantsSubconto.Subconto.TypeValues ​​AS TypeValues,
Types autosuffisantsSubkonto.OnlyTurnover AS OnlyTurnover,
Self-supportingTypesSubconto.Sum AS Sum
À PARTIR DE
Plan de comptes Autosuffisant Types de Subconto AS Autosuffisant

Self-supportingTypesSubkonto.Ref = & Account
TRIER PAR
Types autosuffisantsSubconto.NumberLines

ça ressemble à ça pour moi :

Passons maintenant au concepteur de requêtes. Ici on va s'intéresser à l'onglet "Demande de forfait" :

Comme vous pouvez le voir, nous avons un package de deux demandes. En double-cliquant sur l'un d'eux, vous pouvez procéder à son édition :

Appuyez sur le bouton "Ok" et essayez de voir le résultat de la demande de lot.

Définissons le paramètre "Compte". Vous pouvez sélectionner n'importe quel compte dans le plan comptable. Comme vous l'avez probablement déjà deviné, ce package de demande devrait obtenir les propriétés du compte. Cliquez sur « Exécuter » et voyez le résultat :

Les méthodes Execute() et ExecutePackage()

Lorsque ma requête est devenue si complexe qu'elle était au-delà de ma compréhension, j'ai décidé d'utiliser des requêtes par lots.

Mais j'ai été confronté au fait que je ne sais rien d'eux. Il s'est avéré que tout est très simple. En 5 minutes vous pourrez utiliser les requêtes batch. Commencez à lire.

Il s'est avéré que tout est très simple. Il vous suffit d'écrire plusieurs requêtes séparées par des points-virgules. Le résultat sera retourné dans la dernière requête.

Les requêtes par lots n'apparaissaient que dans la version 8.1.11.67.4.

Voici le texte de la demande :

SÉLECTIONNEZ T1.Zn POSITEZ LES VTLETTRES DE (SÉLECTIONNEZ "A" COMME KN COMBINE TOUT SÉLECTIONNEZ "B") COMME T1 ;

SÉLECTIONNEZ T1.Zn PLACEZ WTDigits DE (SÉLECTIONNEZ "1" COMME KN COMBINE TOUT SÉLECTIONNEZ "2") COMME T1 ;

CHOISISSEZ TB.Zn, TC.Zn, TB.Zn + TC.Zn DE VT Lettres AS TB, VT Chiffres AS TC

Les requêtes par lots sont prises en charge dans n'importe quelle console de requête commune.

La figure montre un exemple d'exécution de requête :

Et maintenant un peu d'expérience. Pourquoi avons-nous besoin de demandes par lots.

Le fait est qu'un résultat intermédiaire peut être attaché à la table temporaire, qui peut alors être nécessaire dans plusieurs requêtes ultérieures.

Auparavant, lorsqu'il n'y avait pas de tables temporaires, vous deviez dupliquer le texte de la requête.

Vous pouvez bien sûr vous passer de la requête par lots en exécutant plusieurs requêtes de manière séquentielle et en manipulant des tables imbriquées. Mais les demandes par lots sont plus pratiques. Vous écrivez simplement une requête et ne pensez pas au placement de tables temporaires. Tout se passe tout seul.

De plus, si un système de composition de données (ACS) est utilisé, il sélectionne intelligemment les champs requis et minimise l'ensemble du lot de requêtes.

Si les requêtes avaient une méthode Demande.Exécuter () alors maintenant il y a une méthode Request.RunPackage () qui renvoie toutes les tables du package, sous forme de tableau.

L'annonce des demandes de lots sur le site 1c est ici : http://v8.1c.ru/overview/release_8_1_11/#Functional

Histoire de la vie

Laissez-moi vous expliquer ce qui m'a incité à faire des demandes par lots.

Alors, imaginez qu'il y a un document, il a partie tabulaire... Dans une colonne " Erreur»Signer s'il y a une erreur lors du remplissage du document. Dans une colonne " Erreurs de texte»Il peut y avoir une ou plusieurs phrases avec des textes d'erreur. Les types d'erreurs contenues dans les propositions sont connus à l'avance.

Ainsi, nous entrons une liste de toutes les erreurs dans le tableau. Codes d'erreur- il contient le code d'erreur et la sous-chaîne de recherche.

Nous obtenons une, deux ou plusieurs erreurs pour chaque ligne. Parce que il peut y avoir plusieurs erreurs sur une même ligne.

Mais l'erreur peut ne pas être reconnue, c'est-à-dire drapeau " Erreur« Stand, et le texte d'erreur ne nous a pas donné de code d'erreur.

On fait la jointure gauche, où le code d'erreur est NULL, on donne le code d'erreur " Autres erreurs» .

Mais le problème était qu'il y avait environ 200 codes d'erreur, donc la jointure gauche a fonctionné très longtemps. J'ai dû le remplacer par une connexion interne qui volait. Mais en même temps, les lignes pour lesquelles l'erreur n'a pas été trouvée ont été perdues. Je n'ai jamais été capable de comprendre comment tirer ces lignes dans le résultat.

La demande a été écrite pour le système de mise en page, c'est-à-dire aucune table de valeurs ou table temporaire ne peut en principe être utilisée. C'est là que les demandes par lots sont arrivées.

J'ai juste encore une fois concaténé toutes les lignes avec des erreurs avec toutes les lignes pour lesquelles des erreurs ont été trouvées, et j'ai quand même ajouté le type d'erreur "Autres erreurs".

L'article décrit le mécanisme de requêtes par lots implémenté dans la plateforme 1C : Enterprise. Après avoir lu l'article, vous découvrirez :

  • Que sont les demandes par lots et à quoi servent-elles ?
  • Comment créer un package de requêtes à l'aide du générateur de requêtes ?
  • Comment renvoyer un tableau de résultats pour chaque requête d'un lot ?

Applicabilité

Le matériel est pertinent pour les versions actuelles de la plate-forme 1C: Enterprise, version 8.3

Objet du lot de demandes

La plate-forme vous permet de travailler avec des demandes par lots. Nous avons la possibilité d'exécuter plusieurs requêtes "à la fois". Dans une demande par lots, les textes de la demande sont séparés par le ";" (point virgule).

Les requêtes sont exécutées de manière séquentielle, tandis que les tables temporaires qui ont été créées lors de l'exécution de toute requête existeront jusqu'à la fin de l'exécution de l'ensemble du lot de requêtes ou jusqu'à l'exécution d'une requête dans le lot qui détruit cette table temporaire. Une différence importanteà partir d'une sous-requête est que les résultats de chaque demande de lot sont disponibles séparément.

Les packages de requêtes vous permettent de réaliser une exécution de requêtes par étapes. Pour ce faire, dans une requête batch, des tables temporaires sont d'abord créées, puis leur utilisation conjointe (jointure, union, filtres) pour obtenir le résultat final de la requête. Il est également important de noter que l'utilisation de tables temporaires dans les requêtes par lots peut améliorer la lisibilité du texte de la requête.

Les requêtes volumineuses avec des requêtes imbriquées enveloppées les unes dans les autres sont souvent assez difficiles à comprendre. Mais si vous réécrivez une telle requête à l'aide de tables temporaires, la visibilité de la requête peut être considérablement améliorée. L'utilisation d'un lot de requêtes avec des tables temporaires peut également améliorer les performances des requêtes.

Il existe des techniques pour optimiser les performances des requêtes basées sur le remplacement des requêtes imbriquées par des tables temporaires.

Une table temporaire peut être utile lorsque vous devez utiliser les mêmes données plusieurs fois dans une requête volumineuse, comme une jointure ou une jointure avec d'autres tables. Lors de l'utilisation de requêtes imbriquées, ces données devraient être récupérées plusieurs fois à l'aide des mêmes requêtes imbriquées, ce qui, bien sûr, affecterait à la fois la lisibilité du texte et les performances.

Créer un package de requête à l'aide du concepteur

Les demandes individuelles incluses dans le package sont séparées dans le texte par le ";" (point virgule). Pour éviter de fractionner manuellement le texte de la requête, vous pouvez utiliser le Concepteur de requêtes pour ce faire.
Le générateur de requêtes a un onglet séparé pour les groupes de requêtes. Les demandes peuvent être ajoutées au package à l'aide du bouton correspondant sur le panneau de commande, et également déplacées vers le haut ou vers le bas.

Affichage visuel des requêtes individuelles - onglets sur le côté droit du concepteur, avec lesquels vous pouvez modifier le texte d'une requête individuelle. Sur ces onglets, des noms sont affichés pour les tables temporaires, pour les demandes de sélection de données - "Demande de lot 2", etc., pour destruction - "- NomBT".

Également dans la liste des tables de base de données apparaissent des tables temporaires créées dans ce paquet... Cependant, cela ne signifie pas que les tables temporaires sont stockées dans la base de données avec toutes les autres tables de l'infobase.

Exécuter les demandes de package

Si l'objet Enquête l'exécution de la requête batch, le gestionnaire de tables temporaires est installé, les tables temporaires qui n'ont pas été détruites lors de la requête batch seront enregistrées dans le gestionnaire installé.

Dans le texte d'une requête batch, il est possible d'utiliser et de détruire les tables temporaires qui existaient dans le gestionnaire de tables temporaires installé au moment du lancement du package pour exécution.

Outre la méthode Exécuter () qui exécute séquentiellement toutes les demandes du package et renvoie le résultat de la dernière demande du package, il existe une autre méthode dans la plate-forme - Exécuter le package ().

Cette méthode exécute toutes les demandes de manière séquentielle et renvoie un tableau de résultats pour chaque demande du package, dans l'ordre dans lequel les demandes apparaissent dans le corps du package.

Le résultat de l'exécution d'une requête pour détruire une table temporaire est la valeur Indéfini qui est également placé dans le tableau des résultats.

Cet article s'adresse aux lecteurs familiarisés avec le langage SQL.

Le langage de requête en 1C, utilisé depuis la version 8, est aujourd'hui devenu outil utile pour travailler avec des bases de données, ce qui vous permet de lire à partir d'elles, mais pas d'écrire. Syntaxiquement, le langage de requête est très similaire au langage SQL, mais en russe.

Ci-dessous un tableau de correspondance entre les principaux opérateurs du langage de requête et SQL :

Opérateurs du langage de requête 1C

instruction SQL

DIVERS

COMPOSÉ

CHARGER PAR

COMBINER

TRIER PAR

Et c'est loin d'être liste complète... Plus achevé Informations d'arrière-plan au à disposition des opérateurs le langage de requête peut être obtenu auprès du concepteur de requêtes, qui sera discuté ci-dessous.

Exécuter une requête 1C de code de programme s'effectue à l'aide de l'objet du langage intégré "Request". Exemple d'écriture d'une requête de base de données à l'aide du langage de programmation embarqué :

Demande = Nouvelle demande ; Request.Text = "SELECT | Synonym.Link AS Link | FROM | Directory.Reference1 AS Synonym"; Sélection = Requête.Exécuter ().Sélectionner (); While Selection.Next () Cycle // Insertion du traitement de la sélection SelectionDetailedRecords Fin du cycle ;

La méthode "Run" exécute la requête, la méthode "Select" retourne une valeur de type "FetchFromQueryResult". Vous pouvez également utiliser la méthode Unload, qui renvoie une table de valeurs.

Les paramètres de la requête sont stockés dans la propriété "Paramètres" (dans ce cas, il s'agit d'une structure, donc toutes les méthodes de structure sont applicables ici - insertion, suppression, etc.).

Un exemple de paramétrage du paramètre "Query.Parameters.Insert" ("Reference", ReferenceLink). Dans une requête, vous pouvez faire référence aux paramètres via l'esperluette "& Référence". Voici un exemple de requête utilisant des paramètres :

Demande = Nouvelle demande ; Request.Text = "SELECT | Users.Link AS Link, | Users.Parent AS Parent, | Users.Name AS Name | FROM | Directory.Users AS Users | WHERE | Users.Link = & Directory"; Request.Parameters.Insert ("Répertoire", DirectoryLink); Sélection = Requête.Exécuter ().Sélectionner (); While Selection.Next () Cycle // Insertion du traitement de la sélection SelectionDetailedRecords Fin du cycle ;

Rappelons que le langage de requête est destiné uniquement à la lecture des données de la base de données, il n'a donc pas d'analogues de tels Instructions SQL comme INS ERT et UPDATE. Les données ne peuvent être modifiées que par modèle d'objet langage de programmation intégré 1C. Dans le langage de requête 1C, il existe également des opérateurs qui n'ont pas d'analogues en SQL, par exemple :

  • DANS LA HIÉRARCHIE
  • LIEU
  • INDEX PAR

DANS LA HIÉRARCHIE- permet de sélectionner tous les éléments du catalogue hiérarchique qui sont inclus dans la hiérarchie du lien passé. Exemple de requête utilisant DANS LA HIÉRARCHIE:

SELECT Goods.Link, Goods.Articul FROM Directory.Goods AS Goods WHERE Goods.Link DANS LA HIÉRARCHIE (& Agrumes) "

Dans ce cas, le résultat renverra tous les éléments subordonnés du catalogue de nomenclature Citrus, quel que soit le nombre de niveaux de hiérarchie de ce catalogue.

Aussi, par exemple, la tâche consiste à trouver un produit portant le nom « Handle ». L'article doit être inclus dans la hiérarchie « Papeterie ». Marchandises », c'est-à-dire que nous n'avons pas besoin de chercher une poignée de porte. La structure de la nomenclature dans ce cas est la suivante :

Chancellerie

| _ Stylos plume | _ Stylo rouge | _ Stylo bleu | _ Stylos à encre | _ Règles

Raccords

| _ Poignées de porte | _ Poignée de porte simple | _ Poignée de porte de luxe

Nous écrivons une requête comme celle-ci :

SÉLECTIONNEZ Products.Link, Products.Article DE Directory.Products COMME Produits O Produits.

Lors de l'utilisation de la conception DANS LA HIÉRARCHIE il convient de garder à l'esprit que si vous passez un lien vide vers le paramètre "Office", la requête ralentira, car la plate-forme vérifiera chaque élément pour l'appartenance à la racine.

LIEU- Cette instruction place le résultat dans une table temporaire. Exemple de requête :

SELECTIONNER Users.Link AS Link, Users.Parent AS Parent, Users.Name AS Name POST Utilisateurs sélectionnés FROM Directory.Users AS Users WHERE Users.Link = & Directory; SELECT Selected Users.Link AS Link, Selected Users.Parent AS Parent, Selected Users.Name AS Name FROM Selected Users AS Selected Users

Cette requête SQL sera exécutée par plusieurs requêtes :

  • Création d'une table temporaire (la plateforme est capable de "réutiliser" des tables temporaires précédemment créées, la création n'a donc pas toujours lieu) ;
  • Mettre des données dans une table temporaire ;
  • Exécuter la requête principale, à savoir SEL ECT à partir de cette table temporaire ;
  • Détruire/nettoyer la table temporaire.

La table temporaire peut être détruite explicitement, par la construction DÉTRUIRE, ou implicitement - lors de la fermeture du gestionnaire de tables temporaires.

L'objet "Query" du langage de programmation embarqué a une propriété "TemporaryTablesManager", qui est destinée à travailler avec des tables temporaires. Exemple de code :

MVT = NewTemporaryTablesManager (); Demande = Nouvelle demande ; Query.TemporaryTablesManager = MVT;

Après l'exécution de la requête, MBT peut être utilisé une seconde fois dans une autre requête, ce qui est sans doute un autre avantage de l'utilisation de tables temporaires. Dans ce cas, la table temporaire sera supprimée de la base de données lors de l'appel de la méthode "Fermer"...

MVT.Fermer ();

... ou lors de l'effacement d'une variable de la mémoire, c'est-à-dire lors de l'exécution de la méthode dans laquelle la variable a été déclarée. Les tables temporaires augmentent la charge sur le sous-système de disque, vous ne devez donc pas créer trop de sous-systèmes temporaires (dans une boucle, par exemple) ou de grands sous-systèmes.

INDEX PAR- cet opérateur est utilisé conjointement avec l'opérateur LIEU. Lors de la création d'une table temporaire, cet opérateur peut indexer la table créée, ce qui accélère considérablement le travail avec elle (mais uniquement si l'index correspond à votre requête).

Consultation gratuite d'experts

Merci pour votre requête!

Un spécialiste 1C vous contactera dans les 15 minutes.

Caractéristiques de certains opérateurs du langage de requête

POUR CHANGERcet opérateur est conçu pour verrouiller une table de requête spécifique (ou toutes les tables qui participent à une requête). Le verrouillage s'effectue en imposant un verrou en U sur la table. En SQL, cela est implémenté via le conseil UPDLOCK. Cette conception est nécessaire pour éviter les blocages. Un exemple de demande avec une construction POUR CHANGER:

SELECTIONNER Users.Link AS Link, Users.Parent AS Parent, Users.Name AS Name FROM Directory.Users AS Users LEFT UNION Directory.RFK AS RFK ON Users.RFK = RFK.Link FOR CHANGE Directory.Users

V cet exemple Le verrou U sera défini sur la table "Utilisateurs". Si vous ne spécifiez pas de table à verrouiller, elle sera superposée à toutes les tables participant à la requête. Il est important de noter que cette conception ne fonctionne que dans les configurations qui incluent mode automatique gestion des blocs.



COMPOSÉ- la demande maintient les connexions GAUCHE / DROITE, PLEIN, INTÉRIEUR, qui correspond aux jointures en SQL - LEFT / RIGHT JOIN, OUTER JOIN, INNER JOIN.

Cependant, lorsque vous utilisez Query Builder, vous ne pouvez pas faire BONNE CONNEXION. Le constructeur échangera simplement les tables, mais l'opérateur sera toujours laissé. Pour cette raison, dans 1C, vous ne verrez jamais l'utilisation de la bonne connexion.

D'un point de vue syntaxique, la connexion ressemble à ceci :

SELECT Table1.Ref AS Link FROM Reference.Reference1 AS Table1 LEFT JOIN Reference.Reference2 AS Table2 BY Table1.Attribute = Table2.Attribute

Dans le langage de requête 1C, il n'y a pas d'opérateur pour joindre un produit cartésien (CROSS JOIN). Cependant, l'absence d'opérateur ne signifie pas que le langage de requête ne prend pas en charge une telle connexion. Si nécessaire, vous pouvez joindre des tables de cette manière :

SELECT Table1.Ref AS Link FROM Reference. Reference1 AS Table1 LEFT JOIN Reference. Reference2 AS Table2 TRUE

Comme vous pouvez le voir dans l'exemple, la clé de connexion est définie VRAI, c'est-à-dire que chaque ligne d'un tableau correspond à une ligne d'un autre. Le type de jointure (LEFT, RIGHT, FULL, INNER) n'est pas important si vous avez des lignes dans les deux tables, mais s'il n'y a aucune ligne dans aucune des tables (abandon de la table), le résultat sera différent. Par exemple, lors de l'utilisation INTERNE le résultat de la connexion sera vide. Utilisant GAUCHE DROITE le résultat sera une jointure ou pas de données, selon la table que nous joignons - avec des données ou non. Utilisant COMPLET les connexions de données seront toujours (bien sûr, une seule table, car il y a du vide dans l'autre), le choix du type de connexion dépend de l'application spécifique.

Un petit indice visuel de leur fonctionnement différents types Connexions:



COMME. Contrairement à l'opérateur similaire langage SQL- LIKE, un modèle pour COMME peut être défini en utilisant uniquement certains caractères spéciaux :

  • % (pourcentage) : une séquence contenant un nombre quelconque de caractères arbitraires ;
  • _ (trait de soulignement) : un caractère arbitraire ;
  • / - Le caractère suivant doit être interprété comme un caractère normal.

RÉSULTATS SUR l'équivalent en SQL est l'opérateur ROLLUP. Exemple d'utilisation de l'opérateur RÉSULTATS:

SELECT Products.Price AS Price, Products.Product AS Product FROM Directory.Nomenclature AS Products MOYENNE TOTALE (Prix) BY Product

Le résultat sera comme ceci :

Lit

9833,333

Fer

Stylo

C'est-à-dire qu'une ligne supplémentaire est ajoutée au résultat contenant la valeur du champ par lequel le regroupement est effectué et la valeur de la fonction d'agrégation.

Travailler avec des requêtes par lots

1C vous permet de travailler avec des packages de demande. Dans une requête par lots, les textes de requête sont séparés par un point-virgule (;). La demande de lot 1C est exécutée de manière séquentielle. Exemple de texte de demande de lot :

SÉLECTIONNEZ Users.Link AS Link, Users.Parent AS Parent, Users.Name AS Name FROM Directory.Users AS Users ;
SÉLECTIONNER Horaire de travail.Utilisateur en tant qu'utilisateur, Horaire de travail.Date en tant que date, Horaire de travail.Heures de travail en tant qu'heures de travail FROM Registre d'informations.Horaire de travail en tant qu'horaire

Pour obtenir le résultat de toutes les demandes incluses dans le package, vous devez utiliser la méthode objet de demande RunPackage au lieu de Run. Cette méthode exécute toutes les requêtes de manière séquentielle. Le résultat d'une requête est un tableau de résultats pour chaque requête du lot, et la séquence dans le tableau est la même que la séquence de requêtes dans le texte du lot.

Compte tenu du langage de requête, il convient de mentionner une fonctionnalité telle que les tables virtuelles. Il n'y a pas de tables virtuelles dans la base de données, c'est une sorte de wrapper qui est exécuté du côté du SGBD en tant que requête utilisant des sous-requêtes. Un exemple de requête 1C utilisant des tables virtuelles :

Registre des obligations SELECT

Une telle requête pour un SGBD ressemblera à ceci :

SEL ECT T1.Fld25931RRef FR OM (SELECT T2._Fld25931RRef AS Fld25931RRef, CAST (SUM (T2._Fld25936) AS NUMERIC (38, 8)) AS Fld25936Turnover_, CAST (SUM (T2._Fld25937) AS NUMICTurn) AS Fld25936Turnover_, CAST (SUM (T2._Fld25937) AS NUMIC37OM) AS Fld25936Turnover_, CAST ._AccumRgTn25938 T2 O ((T2._Fld949 = @ P1)) ET ((T2._Fld25936 @ P2 OU T2._Fld25937 @ P3)) GROUPER PAR T2._Fld25931RRef ÉCONOMIE (T2._Fld25931RRef ÉCONOMIE (T2.36 () COMME NUMÉRIC) 38, 8))) 0,0 OU (CAST (SUM (T2._Fld25937) AS NUMERIC (38, 8))) 0,0) T1 >>>>

On peut voir que cela ne ressemble pas à du SQL, puisqu'il y a une sous-requête, le regroupement. Les tables virtuelles, dans l'ensemble, sont du "sucre syntaxique", c'est-à-dire qu'elles sont créées, en général, pour faciliter le développement de requêtes, afin que les requêtes soient plus compactes et lisibles.

Seuls les registres ont des tables virtuelles, mais quelles tables virtuelles sont disponibles à partir d'un registre peuvent être vues dans le concepteur de requêtes.



Lorsque vous utilisez des tables virtuelles, vous devez toujours donner une condition de sélection. Sinon, des problèmes de performances peuvent survenir.



Dans le texte de la requête, cela ressemble à ceci :

Accumulation Register.LiabilitiesRegister.Turns (, Operation = & Operation) AS Obligation RegisterVooms

Pour plus de commodité, en écrivant des requêtes, c'est-à-dire en créant des textes de requête, dans 1C, il existe un constructeur qui peut être appelé via le menu contextuel (clic droit) :



Dans le concepteur de requêtes, vous pouvez voir une liste complète des fonctions et opérateurs pris en charge du langage de requête.


Le Query Builder est un outil visuel très flexible pour créer des requêtes de toute complexité. Il n'est disponible qu'en mode configurateur. En mode Entreprise, il existe une soi-disant "Console de requête" - c'est traitement externe fourni sur le disque ITS. Pour une application gérée, la console de requête peut être téléchargée à partir de its.1c.ru.

La description du travail dans le concepteur de requêtes dépasse le cadre de cet article, elle ne sera donc pas examinée en détail.

Raisons des performances de requête sous-optimales

Vous trouverez ci-dessous une liste des principales raisons (mais pas toutes) qui ralentissent l'exécution des requêtes.

  • Utiliser des jointures avec des sous-requêtes

Il n'est pas recommandé de se joindre à des sous-requêtes ; les sous-requêtes doivent être remplacées par des tables temporaires. La connexion de sous-requêtes peut entraîner une perte de performances significative, tandis que l'exécution d'une requête sur différents SGBD peut varier considérablement en vitesse. La vitesse d'exécution de telles requêtes est également sensible aux statistiques du SGBD. La raison de ce comportement est que l'optimiseur de SGBD ne peut pas toujours déterminer correctement le plan d'exécution de requête optimal, car l'optimiseur ne sait rien du nombre de lignes que la sous-requête retournera après son exécution.

  • Utilisation de tables virtuelles dans les jointures de requête

Les tables virtuelles au niveau du SGBD sont exécutées en tant que sous-requêtes, les raisons sont donc les mêmes que dans le premier paragraphe.

  • Utilisation de conditions de requête qui ne correspondent pas aux index existants

Si dans les conditions de la requête (dans l'opérateur ou dans les conditions d'une table virtuelle) on utilise des champs qui ne sont pas tous inclus dans l'index, demande donnée sera exécuté avec en utilisant SQL les constructions d'analyse de table ou d'analyse d'index (en tout ou en partie). Cela affectera non seulement le temps d'exécution de la requête, mais également des verrous S excessifs seront imposés sur des lignes supplémentaires, ce qui peut à son tour entraîner une escalade des verrous, c'est-à-dire que la table entière sera verrouillée.

  • Utilisation de OR dans les conditions de requête

Usage opérateur logique OU en construction peut également entraîner une analyse de la table. Cela est dû au fait que le SGBD ne peut pas utiliser correctement l'index. À la place de OU vous pouvez appliquer la construction COMBINEZ TOUT.

  • Obtenir des données à travers un point pour les champs d'un type complexe

Il n'est pas recommandé d'obtenir des valeurs par un point (dans la construction CHOISISSEZ O), car si l'attribut d'objet s'avère être un type composite, la jointure se produira avec chaque table de ce type composite. En conséquence, la requête sur le SGBD sera considérablement compliquée, ce qui peut empêcher l'optimiseur de choisir le plan d'exécution de requête correct.



Vous avez aimé l'article ? Partagez-le