Zoek naar het laatste voorkomen van een teken in tekenreeks 1s. Voorbeelden voor het werken met strings

In dit artikel vertel ik je over de snelzoekfunctie van 1C Enterprise 8. Wat is snel zoeken? Erg makkelijk. Snel zoeken is een van de manieren om door grote lijsten met 1C-records te navigeren. Dit kunnen lijsten zijn van documenten, mappen, registers - alles wat wordt weergegeven door tabellen.

Wat is snel zoeken?

De snelzoekfunctie in 1C Enterprise-documenten is uiterst handig en stelt u in staat niet door enorme hoeveelheden gegevens te scrollen (bijvoorbeeld met behulp van een schuifbalk), maar direct naar de gewenste plek in de lijst. Helaas gebruiken beginnende gebruikers van 1C Enterprise 8 (inclusief 1C Accounting 8) in eerste instantie de snelle zoekmogelijkheden niet, maar scrollen ze liever handmatig door de lijsten met documenten (en ze kunnen heel groot). Dit artikel helpt u erachter te komen hoe u snel zoeken in 1C kunt gebruiken.

Allereerst moet worden opgemerkt dat in 1C Enterprise 8-configuraties, gebouwd op beheerde formulieren, snel zoeken anders werkt dan in eerdere versies van 1C. Daarom zullen we het gebruik van snel zoeken in beheerde formulieren en in reguliere formulieren afzonderlijk analyseren.

Snel zoeken in 1C Boekhouding 8.2

In versies van 1C Accounting van 8.0 tot 8.2 de functie is specifiek bedoeld voor overgang naar het gewenste deel van de lijst. Kijk bijvoorbeeld naar het rekeningschema-venster dat in de afbeelding wordt getoond.


Een bepaalde lijn wordt gemarkeerd in het venster. Let op de subtiele driehoek van strepen aangegeven door de rode pijl. Net als in andere Windows-programma's waar lijsten zijn (bijvoorbeeld in Verkenner), bepaalt de positie van deze markering (driehoek) de sortering van de lijst als geheel - in welke kolom de markering is geplaatst, wordt de hele lijst op die kolom gesorteerd. In de afbeelding staat de markering in de kolom Code, daarom worden de rekeningen in het rekeningschema op code gesorteerd.

De markering kan van de ene kolom naar de andere worden verplaatst door op de gewenste kolom te klikken ( op de HEADER van de kolom!) met de muis. Als de markering al in de huidige kolom staat, verandert de sorteerrichting door te klikken in de tegenovergestelde richting (d.w.z. van groter naar kleiner of omgekeerd). Dit is het standaardgedrag voor alle Windows-programma's. Wat is de eigenaardigheid van deze marker in 1C Enterprise en hoe is deze gerelateerd aan snel zoeken?

Een snelle zoekopdracht in de 1C Enterprise 8-lijsten wordt uitgevoerd door de kolom waarin de markering zich bevindt. In dat geval wordt er snel gezocht in het rekeningschema via de kolom Code.

Er stond een belangrijk deel van het artikel, maar zonder JavaScript is het niet zichtbaar!

Hoe gebruik je snel zoeken in 1C? Eenvoudig! Begin gewoon te typen wat je wilt vinden in DEZE kolom, d.w.z. waar de markering is. In het voorbeeld in de bovenstaande afbeelding moet het rekeningnummer worden ingevuld. U wilt bijvoorbeeld rekening 50 Kassier vinden. Voer in dit geval ( je hoeft nergens te klikken!) het nummer 50 van het toetsenbord, en als er een account is met dit nummer in deze kolom (en natuurlijk is er een), dan zal de lijst naar deze regel scrollen en de regel zelf wordt gemarkeerd. Het resultaat wordt getoond in de schermafbeelding van het rekeningschema hieronder.

site_

De tekst waarnaar wordt verwezen door de pijl is niet nodig om te wassen- hijzelf zal verdwijnen.

Als u in het gegeven voorbeeld het woord "Kassier" begint in te voeren, wordt de tekst in het onderste deel van het venster ingevoerd en vervolgens gewist. Dit gebeurt omdat zodra: Begin van de ingevoerde snelzoekreeks niet meer samenvalt met het begin van ten minste één regel in deze kolom, concludeert 1C Enterprise dat de zoekreeks niet is gevonden en wist deze automatisch. Met betrekking tot er zijn twee regels om te onthouden:.

In 1C Enterprise 8 wordt snel gezocht aan het begin van de regel, d.w.z. de kolom zoekt naar een overeenkomst tussen de ingevoerde tekst en het begin van een van de regels van deze kolom.
Dit leidt tot een belangrijke aanbeveling: bij het invoeren van gegevens in directory's, geef de elementen een naam zodat het gemakkelijk is om ze snel te zoeken. Zo kan de naam van de tegenpartij beter worden geschreven als "NameFirm LLC" dan "LLC NameFirmy". Bovendien moet je geen aanhalingstekens en andere onnodige symbolen in de naam gebruiken (we hebben het over het invullen van het veld Naam in formulieren).

Als u begint met het typen van tekst en deze is gewist - wat u zoekt, staat niet in deze kolom! Controleer in dit geval de invoertaal, evenals de kolom waarin de snelle zoekopdracht wordt uitgevoerd. Een veelgemaakte fout is dat de verkeerde kolom is geselecteerd. De markering wordt bijvoorbeeld ingesteld in de kolom Code en de zoekopdracht wordt uitgevoerd op de naam van het account.

Snel zoeken in 1C Boekhouding 8.3

Laten we nu eens kijken hoe snel zoeken verschilt in 1C Enterprise 8.3. Het gebruik lijkt erg op 8.2, maar er is één belangrijk verschil om te onthouden.

In 1C Accounting 8.3, evenals in alle andere configuraties op beheerde formulieren (dezelfde nieuwe interface), werkt het als een filter. Simpel gezegd, als resultaat van de snelzoekfunctie, een deel van de lijst verstoppen.

Hoe u dit gebruikt, gaan we nu met u uitzoeken. Bekijk eerst de schermafbeelding van het 1C Accounting 8.3 rekeningschema-venster hieronder.

site_

Zoals je kunt zien, staat dezelfde markering in een van de kolommen. De zoekopdracht wordt ook uitgevoerd door de kolom waarin de markering is geplaatst. Dit alles bleef onveranderd. Als u echter begint met het invoeren van tekst (in het voorbeeld het rekeningnummer), gebeurt het volgende.

site_

Zoals u kunt zien, is het zoekvak zojuist automatisch geopend. Hetzelfde venster wordt geopend als u op de zoekknop op de werkbalk van het venster klikt (onderstreept in de afbeelding). Als gevolg hiervan, wanneer u op de knop Zoeken in het zoekvenster klikt (verborgen achter het vervolgkeuzemenu in de afbeelding) of gewoon op Enter, krijgt u het volgende resultaat.

site_

Hieruit blijkt duidelijk dat snel zoeken in 1C Accounting 8.3 laat slechts een deel van de lijst zichtbaar dat aan de zoekvoorwaarden voldoet. In dit geval verdwijnt de knop Zoeken en in plaats daarvan verschijnt er een lens met een kruis (onderstreept in de afbeelding), wanneer u erop klikt, keert de lijst terug naar de oorspronkelijke staat (de regel die is gevonden als resultaat van een snelle zoekopdracht blijft gemarkeerd ).

Een ander belangrijk kenmerk van snel zoeken in 1C Accounting 8.3- er wordt niet gezocht naar een match aan het begin van een regel, zoals in versie 8.2, maar er wordt gezocht naar een match met een deel van de regels in de kolom. Dus als de tegenpartij "NameFirm LLC" heet en bij het zoeken begint met het invoeren van "NameFirm LLC", dan wordt de regel nog steeds gevonden!

Conclusies trekken

Zo is een snelle zoekopdracht in 1C Accounting 8.2 en eerder bedoeld om de lijst naar de gewenste regel te scrollen, en in 1C Accounting 8.3 werkt een snelle zoekopdracht als een gewone filter, waarbij het deel van de lijst wordt verborgen dat u niet nodig hebt.

Er zijn weinig mechanismen om met strings in 1C-query's te werken. Eerst kunnen de lijnen worden toegevoegd. Ten tweede kun je een substring uit een string halen. Ten derde kunnen strings worden vergeleken, ook op patroon. Dat is waarschijnlijk alles wat je met snaren kunt doen.

Aaneenschakeling van strings

Om strings in een query toe te voegen, wordt de bewerking "+" gebruikt. Alleen lijnen van beperkte lengte kunnen worden gevouwen.

SELECTEER "Naam:" + Tegenpartijen. Naam AS Kolom1 UIT Directory. Tegenpartijen AS Tegenpartijen WAAR Tegenpartijen. Link = & Link

Substring functie

SUBSTRAAT (<Строка>, <НачальнаяПозиция>, <Длина>)

Analoog van de functie Omgeving () uit het objectmodel. De functie Subtekenreeks () kan worden toegepast op gegevens van een tekenreekstype en stelt u in staat een fragment te selecteren <Строки> beginnend met het tekennummer <НачальнаяПозиция> (tekens in de string zijn genummerd vanaf 1) en lengte <Длина> karakters. Het resultaat van het evalueren van de functie heeft een stringtype met variabele lengte en de lengte wordt als onbeperkt beschouwd als <Строка> heeft onbeperkte lengte en parameter <Длина> niet constant is of groter is dan 1024.

Als de lengte van de tekenreeks kleiner is dan de lengte die is opgegeven in de tweede parameter, retourneert de functie een lege tekenreeks.

Aandacht! Het wordt niet aanbevolen om de functie SUBSTRING () te gebruiken om strings van onbeperkte lengte om te zetten in strings van beperkte lengte. Het is beter om in plaats daarvan een cast-bewerking zoals EXPRESS () te gebruiken.

Functie Vind ik leuk:

Als we ervoor moeten zorgen dat een tekenreeksattribuut aan bepaalde criteria voldoet, vergelijken we het:

SELECTEER Tegenpartijen Naam AS Kolom1 UIT Directory Tegenpartijen AS Tegenpartijen WHERE Tegenpartijen Naam = "Gazprom"

Maar wat als u een lastigere vergelijking wilt? Niet alleen gelijkheid of ongelijkheid, maar graag een bepaald patroon? Dit is precies waar de functie LIKE voor is gemaakt.

LIKE - Operator voor het controleren van een string zoals een patroon. Analoog van LIKE in SQL.

Met de LIKE-operator kunt u de waarde van de expressie die links ervan is opgegeven, vergelijken met de sjabloontekenreeks die rechts is opgegeven. De expressiewaarde moet van het type string zijn. Als de uitdrukkingswaarde overeenkomt met het patroon, resulteert de operator in TRUE, anders - FALSE.

De volgende tekens in de sjabloontekenreeks zijn servicetekens en hebben een andere betekenis dan het tekenreeksteken:

  • % (percentage): een reeks die een willekeurig aantal willekeurige tekens bevat;
  • _ (underscore): één willekeurig teken;
  • […] (Een of meer tekens tussen vierkante haken): elk afzonderlijk teken tussen vierkante haken. De opsomming kan bereiken bevatten, bijvoorbeeld a-z, wat betekent dat een willekeurig teken in het bereik is opgenomen, inclusief de uiteinden van het bereik;
  • [^…] (tussen vierkante haken een ontkenningsteken gevolgd door een of meer tekens): elk afzonderlijk teken anders dan de tekens die achter het ontkenningsteken staan.

Elk ander symbool betekent zichzelf en heeft geen extra betekenis. Als het nodig is om een ​​van de vermelde karakters als zichzelf te schrijven, moet dit worden voorafgegaan door<Спецсимвол>... Mezelf<Спецсимвол>(elk geschikt teken) wordt gedefinieerd in dezelfde instructie na het sleutelwoord SPECIAL CHARACTER.

Een string is een van de primitieve datatypes in 1C: Enterprise 8. Variabelen met het type lijn tekst bevatten.

Waarden van typevariabelen lijn staan ​​tussen dubbele aanhalingstekens. Er kunnen meerdere variabelen van dit type worden toegevoegd.

Per1 = "Woord 1";
Per2 = "Woord 2";
Per3 = Per1 + "" + Per2;

Eventueel Per3 zal bedoelen " Woord 1 Woord 2 .

Daarnaast bieden 1C: Enterprise 8-systemen functies voor het werken met strings. Laten we de belangrijkste bekijken:

Voer tekenreeks in (<Строка>, <Подсказка>, <Длина>, <Многострочность>) — de functie is bedoeld om een ​​dialoogvenster weer te geven waarin de gebruiker de waarde van een variabele van het type kan specificeren Lijn... Parameter <Строка> is vereist en bevat de naam van de variabele waarnaar de ingevoerde string zal worden geschreven. Parameter <Подсказка> optioneel is de titel van het dialoogvenster. Parameter <Длина> optioneel, geeft de maximale lengte van de invoerreeks aan. De standaardwaarde is nul, wat een onbeperkte lengte betekent. Parameter <Многострочность> optioneel. Bepaalt de invoermodus voor tekst met meerdere regels: True - invoer van tekst met meerdere regels met scheidingstekens; False - invoer van een eenvoudige string.

De string kan worden ingevoerd en de Unicode-tekencode krijgen:

Symbool(<КодСимвола>) — de code wordt ingevoerd als een getal.

Letter = Symbool (1103); // IK BEN

Er is ook een inverse functie waarmee u de code van een teken kunt achterhalen.

SymboolCode (<Строка>, <НомерСимвола>) — retourneert het opgegeven Unicode-tekennummer als een getal.

Functies voor case-conversie:

BReg (<Строка>) - converteert alle tekens in de tekenreeks naar hoofdletters.

HPreg (<Строка>) - converteert alle tekens in een string naar kleine letters.

Treg (<Строка>) - converteert alle tekens in een string naar hoofdletters. Dat wil zeggen, de eerste letters van alle woorden worden omgezet in hoofdletters en de overige letters worden omgezet in kleine letters.

Functies voor het zoeken en vervangen van tekens in een string:

Vinden(<Строка>, <ПодстрокаПоиска>) - vindt het tekennummer van het voorkomen van de zoeksubstring. Bijvoorbeeld:

Zoek ("String", "Oka"); // 4

Vinden (<Строка>, <ПодстрокаПоиска>, <НаправлениеПоиска>, <НачальнаяПозиция>, <НомерВхождения>) - vindt het tekennummer van het voorkomen van de zoeksubstring, het nummer van het voorkomen wordt aangegeven in de bijbehorende parameter. In dit geval begint de zoekopdracht met het teken, waarvan het nummer is opgegeven in de parameter Startpositie. Zoeken is mogelijk vanaf het begin of vanaf het einde van de string. Bijvoorbeeld:

Getal4 Voorvallen = StrFind ( "Defensie vermogen", "o", zoekrichting. Vanaf het begin, 1, 4); // 7

PVervang (<Строка>, <ПодстрокаПоиска>, <ПодстрокаЗамены>) - vindt alle exemplaren van de zoeksubstring in de originele string en vervangt deze door de vervangende substring.

StrReplace ("String", "Oka", ""); // Bladzijde

Lege regel(<Строка>) - controleert een string op significante karakters. Als er geen significante tekens zijn, of helemaal geen tekens, wordt de waarde geretourneerd Waar... Anders - Leugen.

StrAantal voorvallen (<Строка>, <ПодстрокаПоиска>) - berekent het aantal voorkomens van de zoeksubstring in de originele string.

StrAantal voorvallen ( "Studeren, studeren en nog eens studeren", "studeren" , "" ) ; // 3

StrPatroon (<Строка>, <ЗначениеПодстановки1>…<ЗначениеПодстановкиN> — vervangt parameters in de string op nummer. De tekenreeks moet vervangingsmarkeringen bevatten van de vorm: "% 1 ..% N". Markeringen zijn genummerd vanaf 1. Als de parameterwaarde Niet gedefinieerd, wordt een lege string vervangen.

StrPatroon ( "Parameter 1 =% 1, Parameter 2 =% 2", "1" , "2" ) ; // Parameter 1 = 1, Parameter 2 = 2

String conversie functies:

Een leeuw(<Строка>, <ЧислоСимволов>) - retourneert eerst de eerste tekens van de tekenreeks.

Rechts (<Строка>, <ЧислоСимволов>) - geeft de laatste karakters van de string terug.

Woensdag (<Строка>, <НачальныйНомер>, <ЧислоСимволов>) - retourneert een string van lengte<ЧислоСимволов>beginnend met het karakter<НачальныйНомер>.

Afgekort (<Строка>) kapt onbelangrijke tekens links van het eerste significante teken in de tekenreeks af.

Afkorting (<Строка>) - snijdt onbeduidende tekens rechts van het laatste significante teken in de tekenreeks af.

SocrLP (<Строка>) - snijdt onbeduidende tekens links van het eerste significante teken in de regel en rechts van het laatste significante teken in de regel af.

StrGetString (<Строка>, <НомерСтроки>) - krijgt een reeks met meerdere regels op nummer.

Andere functies:

SterkteLengte (<Строка>) - geeft het aantal tekens in een string terug.

StrAantal regels (<Строка>) - retourneert het aantal regels in een tekenreeks met meerdere regels. Een regel wordt als nieuw beschouwd als deze van de vorige regel wordt gescheiden door een teken voor een nieuwe regel.

Vergelijken (<Строка1>, <Строка2> ) - vergelijkt twee strings, niet hoofdlettergevoelig. De functie werkt op dezelfde manier als een object Vergelijking van waarden... Geeft terug:

  • 1 - als de eerste regel groter is dan de tweede
  • -1 - als de tweede regel groter is dan de eerste
  • 0 - als strings gelijk zijn

StrCompare ("Eerste regel", "Tweede regel"); // een

Mijn naam is Pavel Barketov, ik werk voor Softpoint. We lossen al meer dan 10 jaar prestatie-optimalisatieproblemen op. En ondanks het grote aantal opgeloste problemen, neemt hun aantal niet af, maar exponentieel toe. De hoeveelheden data nemen toe en de taken om het werk met deze data te optimaliseren worden moeilijker. Dit proces is onvermijdelijk.

Onderwerp van het artikel - niet-triviale benaderingen voor optimalisatie... Wordt overwogen twee aspecten::

  • Eerste - subtekenreeks zoeken... Gebruikers gebruiken het vaak, en velen hebben waarschijnlijk al te maken gehad met een aanzienlijke verwachting dat zoekopdrachten op substrings niet snel genoeg zijn.
  • Seconde - grote documenten vasthouden, zoals het afsluiten van de maand, het berekenen van de kosten. Velen zijn vast wel eens tegengekomen dat accountants deze documenten 5-9 uur besteden, 's nachts en buiten werkuren. Het meest interessante is dat klassieke optimalisatiemethoden hier niet altijd helpen. Als u een prestatiemeting uitvoert in de debugger terwijl u dergelijke documenten uitvoert, zult u zien dat de grootste hoeveelheid tijd wordt besteed aan het schrijven naar tijdelijke of echte structuren - tabellen, registers, enz. En het is onmogelijk om dit probleem op te lossen met klassieke methoden.

Zoeken op subtekenreeks

Het eerste onderwerp is zoeken op subtekenreeksen. In de loop van dit jaar ben ik verschillende problemen tegengekomen met deze operatie. U komt naar de verzekeringsmaatschappij om de polis te verlengen, zij bieden aan u op telefoonnummer te zoeken. Het is duidelijk dat dit geen klassieke zoektocht naar het volledige telefoonnummer is, omdat de gebruiker het nummer via de acht, via de zeven of iets anders kan invoeren, daarom zoeken ze naar fragmenten van het nummer. In dit geval worden zoekbewerkingen voor de lange termijn gebruikt - in sommige situaties kan de vertraging enkele seconden zijn of oplopen tot minuten.

Zoeken op begintekens

Ik zal beginnen met het eerste voorbeeld, wanneer de zoekopdracht wordt uitgevoerd op de starttekens. Dit is een speciaal geval van een substring-zoekopdracht, wanneer de gebruiker zeker weet dat de zoekwaarde met bepaalde tekens begint.

Zoeken op begintekens is geïmplementeerd in 1C met behulp van het commando LIKE(of in het Engels, LIKE) gevolgd door een waarde met "%" aan het einde ("%" geeft een reeks van andere tekens aan). Wij zijn bijvoorbeeld op zoek naar:

Naam LIKE "ivano%"

Houd er rekening mee dat als u een index op dit veld in uw systeem heeft, dan: in de SQL-query wordt Index Seek gebruikt voor deze zoekopdracht is een indexzoekopdracht.

De voorwaarde "LIKE zoekreeks" is gelijk aan zoeken in een reeks waarden... In het speciale geval, wanneer we zoeken naar "ivano%" - dit komt overeen met zoeken in een reeks achternamen die beginnen met "ivano" en eindigen met "ivanp" (omdat het "p"-teken na het "o"-teken komt ).

Moderne optimizers zetten een LIKE-zoekopdracht onafhankelijk om in een bereikzoekopdracht.... Daarom, als u een index op dit veld in uw systeem heeft, krijgt u precies hetzelfde resultaat bij het interpreteren van de query in SQL-termen - de optimizer zal de query presenteren met LIKE als een bereikzoekopdracht.

Zo is het mogelijk om de klassieke snelle zoekactie uit te voeren met behulp van de Index (Index Seek). Hier zijn geen problemen mee, of je kunt ze op een simpele manier oplossen.

Zoeken op item

Laten we nu een ingewikkelder voorbeeld nemen, wanneer het niet precies bekend is waar in de string onze gewenste waarde is, en er wordt gezocht op het voorkomen van de string. In dit geval staat in de zoekopdracht "LIKE" "%" aan beide kanten.

Bij het omzetten van zo'n query naar SQL zien we dat alleen het commando verandert (de waarde bevat al twee "%").

Laten we het uitvoeringsplan eens nader bekijken. Hier we zien dezelfde Index Seek, maar in dit geval werkt het niet efficiënt.

Feit is dat de index met de naam van het naslagwerk, dat we overwegen, uit meerdere velden bestaat.

  • De eerste is de boekhoudkundige scheidingsteken.
  • Vervolgens komt direct het zoekveld.

En daarom, wanneer "Index Seek" wordt weergegeven in het uitvoeringsplan, betekent dit dat: de zoekopdracht wordt gedaan op het eerste veld van het scheidingsteken- op de dia hierboven zie je dat zoeken op onze gewenste Desc waarde wordt absoluut niet gebruikt.

Wat te doen in deze situatie? In mijn praktijk was het heel vaak voor gebruikers verboden om toegangsverzoeken te gebruiken. En in sommige gevallen hebben gebruikers zelf deze functionaliteit niet gebruikt, omdat de uitvoeringstijd erg groot is, maar ze moeten blijven werken. Daarom moesten ze op andere manieren naar buiten komen - ze kozen in de lijsten, probeerden de eerste tekens te vinden, enzovoort.

Maar dit leidt tot ontevredenheid over de functionaliteit en misvatting van het systeem. De gebruiker begrijpt dat het systeem iets niet aankan en niet werkt zoals verwacht. Het is niet goed.

Een niet-triviale benadering om het probleem van het zoeken naar subtekenreeksen op te lossen

Laten we nu eens kijken naar niet-triviale benadering om dit probleem op te lossen.

Laten we een aantal toleranties aanduiden:

  • Ten eerste sinds modern schijven zijn onbeperkt, laten we zeggen dat je veel schijfruimte hebt die je kunt gebruiken.
  • Seconde - de gebruiker zoekt niet op een of twee tekens, maar op een fragment... Niemand van ons zoekt bijvoorbeeld naar "al" - dit is te weinig selectiviteit. Op zoek naar een betekenisvolle reeks karakters. Hier hebben we ervoor gekozen om als voorbeeld zes karakters te zoeken.

Een voorbeeld van de vereiste string "alexe" is in het formulier geschreven en we zullen het met zijn hulp testen.

  • Stel we hebben een veld met de achternaam, voornaam en patroniem van een klant. De eerste stap is om deze waarde automatisch te ontleden in fragmenten van zes tekens met een verschuiving van "1" en we krijgen een array van fragmenten (zie hierboven), die tegelijkertijd altijd tot de gewenste waarde behoren. We hebben fragmenten die de gebruiker theoretisch kan invoeren. Op de laatste dia werd namelijk vastgesteld dat we op zoek zijn naar zes karakters. Er kunnen er vijf of vier zijn, alleen de grootte van de structuur zal groter zijn.

  • In de tweede stap gaan we we schrijven deze sets in een aparte structuur(het kan een tabel zijn, informatieregister, enz.) en we krijgen een selectie waarin een bepaald fragment tot verschillende waarden behoort.

  • En bij de derde stap, bij het zoeken op subtekenreeks, voegen we een aanvullende EN-voorwaarde toe aan de 1C-queryconstructie "LIKE", die het aantal mogelijke combinaties filtert, en trekken uit deze aanvullende structuur (het kan een informatieregister zijn) alle elementen waartoe de benodigde fragmenten behoren lijnen.

Een gebruiker is bijvoorbeeld op zoek naar een klant met de achternaam "Soldaten". Dit zijn acht tekens, wat betekent dat er drie fragmenten van zes tekens lang zullen zijn, waarnaar we op zoek zijn in de servicestructuur. Dit alles combineren we vervolgens in een aanvraag. Zo wordt extra filtering verkregen.

Als gevolg hiervan verwijderen we het "%"-teken (dat wil zeggen, er zal altijd het teken zijn dat we nodig hebben voor deze fragmenten), en bij het uitvoeren van de interne query, zal de Index Seek gaan, waarvoor we hebben gevochten.

In de praktijk blijkt een heel interessant verhaal - versnelling met tientallen, honderden keren... Bovendien kan dit allemaal door middel van 1C, wat erg prettig is. Het is niet nodig om de logica te herschrijven, de gebruiker zal blij zijn dat zijn zoekopdracht is versneld. In het voorbeeld, versnelling van 4 seconden naar 0,05 seconden, en als we een verzoek aanvankelijk gedurende twee minuten hadden laten uitvoeren, zou het in minder dan een seconde worden uitgevoerd.

Het mechanisme dat ik je liet zien is geen experimenteel voorbeeld, het werkt al bij echte klanten.

Voorbereidende activiteiten voor implementatie

Nu zal ik kort ingaan op de voorbereidende activiteiten.

  • Eerste het is noodzakelijk om het register te vullen met beginwaarden... Hiervoor moeten we een gepland venster plannen.
  • Vervolgens moeten we de consistentie van de gegevens observeren - dit betekent, er moet een abonnement zijn om de waarde te wijzigen zodat deze fragmenten automatisch opnieuw worden opgebouwd.
  • En de laatste - voeg een standaard zoekformulier toe.

Het invullen van registers kan zowel door middel van 1C als met behulp van SQL.

Ik kan zeggen dat het invullen van zo'n structuur voor 17 miljoen waarden ongeveer 20-25 minuten duurt. Uiteraard mogen gebruikers op dit moment de waarden van de zoekopdracht niet wijzigen.

Rekenen we voor een miljoen waarden ergens rond de 100 karakters bij 6 in een fragment, dan komen we ergens op 4,7 GB. Je moet plannen zodat je deze plek hebt. Als je bijvoorbeeld 100 miljoen waarden in de directory hebt staan, dan moet je plannen voor de ruimte die op schijf beschikbaar komt.

De noodzaak om rekening te houden met de statistieken van de populariteit van fragmenten

Werkt deze methode altijd snel?

Dit wordt beïnvloed door fragment populariteitsstatistieken.

  • U hebt bijvoorbeeld een fragment "alexe", dat kan worden opgenomen in de naam Aleksey, in het patroniem Alekseevich, in de achternaam Alekseenko, enz. Dit fragment kan worden opgenomen in 50-100 duizend records.
  • En er zijn zelden gebruikte fragmenten.

Zo verschijnen de statistieken van populariteit door fragmenten.

Let daar op als de populariteit van de fragmenten laag is (100 elementen), dan krijgen we een versnelling van 0,1 seconde.

Als de substring populair genoeg is (50 duizend elementen), dan krijgen we degradatie, en veel meer dan wanneer er geen optimalisatie zou zijn.

Op deze manier, het is noodzakelijk om een ​​verbeterd query-uitvoeringsschema te maken, waarin we eerst de waarde van de populariteit van de subquery zouden krijgen. Dit gebeurt in drie tot vijf regels in 1C. Tegelijkertijd weten we zeker dat als een regel impopulair is, deze de eerste tak volgt, en als hij populair is, volgt hij de tweede.

Hoe werkt versnelling? Er is een zoekopdracht van het formulier, dan gaan we naar het informatieregister met statistieken, halen het element op en kiezen dan wat we willen gebruiken - een klassiek of een versneld verzoek.

Laten we nu eens kijken hoe een SQL-query wordt uitgevoerd op een SQL-server.

De dia toont een vereenvoudigd diagram:

  • er is een verzoek aan de optimizer;
  • we kijken naar statistieken over de velden die in het verzoek worden gebruikt;
  • we kiezen welk uitvoeringsplan we willen gebruiken, dat wil zeggen, we kiezen een strategie voor het uitvoeren van query's (bijvoorbeeld een geneste lus).

Hoe ziet het circuit dat we hebben geïmplementeerd eruit?

  • We hebben onze gemaakt inhoudsopgave... Geen standaard SQL-index, geen 1C-index, maar je eigen index, die nodig is om dit probleem op te lossen;
  • Bovendien werden ze geconfronteerd met het feit dat ze hun eigen statistieken;
  • En je hebt je eigen nodig optimalisatieprogramma, die op basis van deze statistieken beslist welke tak wordt geselecteerd.

Op basis van deze logica kunnen we zeggen dat dit proces de betekenis onthult van waar we indexen, statistieken en een optimizer voor nodig hebben.

Wie niet wist waarom je statistieken in SQL moet dienen, kijk eens naar deze logica, en je zult begrijpen dat als het onjuist of irrelevant is, we naar de verkeerde tak gaan. Het verzoek wordt langzamer. We begrijpen waarom we statistieken efficiënt en correct moeten aanbieden - dit heeft invloed op de prestaties, de index.

Als er geen index is, scannen we alle waarden.

We hebben dus op zijn minst een primitieve, maar onze eigen optimizer gemaakt. We kunnen zeggen dat ze "op hun vingers" voelden hoe MS SQL en andere DBMS het doen, en hun eigen structuren creëerden.

Het versnellen van "grote" documenten

We gaan verder met het tweede onderwerp - het versnellen van grote documenten.

Bij productietaken worden we vaak geconfronteerd met een soort routineprocedures, zoals het afsluiten van de maand, rapporteren aan de agent, het berekenen van de kosten. Deze zware, massieve documenten nemen een aanzienlijke hoeveelheid tijd in beslag om te voltooien en te voltooien. En als we naar de debugger kijken en deze bewerkingen traceren, zien we dat: 1C voegt waarden regel voor regel in een tabel in en dit kost de meeste tijd... En er kan niets aan gedaan worden. De enige aanbeveling die kan worden gedaan is om de schijf te versnellen (de effectiviteit van deze oplossing is zeer twijfelachtig en vereist voorafgaande analyse).

Ik stel voor om terug te gaan naar de geschiedenis en te bekijken hoe het in 1C werd gedaan, van 8.0 tot 8.3 - dit gebeurde regel voor regel... De SQL-server analyseerde het verzoek elke keer, verwerkte het, maakte een uitvoeringsplan, voegde het toe, stuurde een commando naar 1C over succes en ontving het volgende verzoek. En zulke stapsgewijze verzoeken werden van de 1C-applicatieserver naar MS SQL gestuurd.

Het is duidelijk dat als u 40 records in het document heeft, er geen problemen zouden moeten zijn. Als u 10 duizend of meer records heeft (er zijn organisaties met een miljoen records in regelgevende documenten), dan duurt dit proces erg lang. Eén record wordt heel snel verwerkt, maar het zijn er te veel in het document. Wat zijn de overheadkosten? Naar het netwerk, om een ​​verzoek uit te voeren, naar een retoursignaal, om dit signaal in het 1C-systeem te verwerken - in totaal de som van vier fasen. Alle stadia worden samengevat, vermenigvuldigd met een miljoen regels, en we krijgen onze lange verwachtingen. Het is duidelijk dat dit niet verschrikkelijk is.

In 1C zijn vanaf 8.3 verbeteringen aangebracht. Nu wordt een query voor het invoegen in tijdelijke tabellen en informatieregisters voorbereid op de SQL-server, en de verdere uitvoering vindt plaats met behulp van klassieke RPC-aanroepen, waarbij de 1C-toegangsprovider zelf (Native of OLE DB) groepeert records en voegt ze in met N regels (meestal 100 regels).

Zo wordt een versnelling van 30% tot 300% bereikt. Maar dit is nog steeds niet genoeg, want vandaag heb je 10 duizend lijnen, morgen 20 duizend lijnen. Dit is geen fundamentele oplossing voor het probleem, u zult er nog steeds mee te maken krijgen, maar pas na zes maanden / een jaar.

Die snelste invoeging naar een SQL-server, en inderdaad naar een DBMS?

Deze BULK INSERT... In 1C wordt BULK INSERT gebruikt, maar voor andere taken. Ik zou ook het werk met "grote" documenten willen versnellen door INSERT-inserts te vergroten en records in een enkele array toe te voegen aan de SQL-serverdatabase.

Laten we eens kijken welk effect wordt bereikt. In het beschouwde voorbeeld verkregen we acceleratie is ongeveer 5 keer, maar je kunt 10 keer versnellen... In theorie is het grootste probleem om dit aanzienlijk meer te versnellen de schijfsnelheid. De schijf kan een bottleneck zijn.

Ook het is belangrijk om te onthouden over een criterium als indices... Als we een BULK INSERT in de tabel zouden invoegen zonder de indexen bij te werken, dan zouden we een aanzienlijke versnelling krijgen (resulteert in minder dan een seconde). Hier krijgen we 69 seconden omdat elke invoeging in de tabel een REFRESH-index vereist.

Met deze methode kunt u in ieder geval het effect van 5-10 keer bereiken.

Bovendien worden functies als partitionering en partitionering hier niet beschouwd. De situatie zou verbeterd kunnen worden als we wisten dat BULK INSERT wordt ingevoegd in de huidige periode, en we de irrelevante naar een andere partitie zouden verplaatsen. Het zou nog effectiever zijn. Het blijkt dat de acceleratie erg goed is.

De optimalisatiemogelijkheden zijn eindeloos

Op deze manier, de optimalisatiemogelijkheden zijn eindeloos... Het enige is dat je je niet laat meeslepen. Voor optimalisatie is het altijd zinvol om te berekenen of het beoogde effect zal zijn of niet. Ook zou ik in sommige situaties adviseren om boven het probleem uit te stijgen, niet de klassieke methoden van query-optimalisatie te gebruiken, maar een aantal totaal andere die significantere resultaten kunnen opleveren.

****************

Dit artikel is geschreven op basis van de resultaten van het rapport () gelezen op de INFOSTART EVENT 2017 COMMUNITY-conferentie.