What is logical NOT operator?

Bitmap-operatoren i SQL: En Dybdegående Guide

29/03/2023

Rating: 4.32 (12458 votes)

I en verden af databaseoptimering er der mange værktøjer og operatører, som hjælper os med at skrive hurtigere og mere effektive forespørgsler. Mens de fleste udviklere kender til almindelige join-typer som INNER JOIN eller operatører som Table Scan, er der andre, mere specialiserede operatører, der arbejder i kulissen for at levere imponerende ydeevneforbedringer. En af disse er Bitmap-operatoren. Selvom den måske er mindre kendt, spiller den en afgørende rolle i håndteringen af store datamængder, især når en forespørgsels eksekveringsplan kører parallelt. Denne artikel vil dykke ned i, hvad en Bitmap-operator er, hvordan den fungerer, og hvorfor den er så vigtig for ydeevnen.

What is a bitmap operator?
A bitmap operator is a way to perform a "semijoin reduction" operation (a process that excludes rows from the subsequent join operation) The gain from joining fewer rows must be greater than the cost of running the bitmap operator Now let's talk about what it is and how it works.
Indholdsfortegnelse

Hvad er en Bitmap-operator?

En Bitmap-operator er en specialiseret operator, som SQL Server's forespørgselsoptimerer kan vælge at bruge for at forbedre ydeevnen ved at filtrere data så tidligt som muligt i en eksekveringsproces. Dens primære formål er at udføre en operation kendt som "semijoin-reduktion". Forestil dig, at du skal joine to meget store tabeller. Uden en Bitmap-operator ville databasesystemet måske skulle læse millioner af rækker fra den ene tabel, kun for at opdage, at de fleste af dem ikke har et match i den anden tabel. Dette er spild af ressourcer.

Her kommer Bitmap-operatoren ind i billedet. Den skaber en kompakt datastruktur – et "bitmap" – baseret på den ene (typisk den mindre) tabel i joinet. Dette bitmap fungerer som et hurtigt opslagsfilter. Før det dyre join-arbejde overhovedet begynder, bruges dette filter til at scanne den anden (større) tabel og øjeblikkeligt kassere alle de rækker, der med garanti ikke vil finde et match. Resultatet er, at kun en brøkdel af de oprindelige rækker sendes videre til selve join-operatoren, hvilket sparer en enorm mængde CPU-tid og I/O. Denne mekanisme er især effektiv i parallelle eksekveringsplaner, hvor data fordeles over flere tråde.

Et Praktisk Eksempel: Bitmap i Aktion

For virkelig at forstå, hvornår og hvorfor en Bitmap-operator anvendes, er det bedst at se på et konkret eksempel. Lad os forestille os et scenarie med to tabeller, TabA og TabB.

TabA er vores mindre tabel og indeholder omkring 1.000 rækker. TabB er vores massive tabel med over 10 millioner rækker. Begge tabeller har en kolonne ved navn Progr af typen integer, som vi vil bruge til at joine dem.

Lad os nu køre to meget ens forespørgsler:

Forespørgsel 1:

SELECT * FROM TabA a JOIN TabB b ON a.Progr = b.Progr WHERE b.Progr >= 500;

Forespørgsel 2:

SELECT * FROM TabA a JOIN TabB b ON a.Progr = b.Progr WHERE b.Progr >= 501;

Selvom disse forespørgsler ser næsten identiske ud, kan deres eksekveringsplaner være vidt forskellige. I dette specifikke scenarie vil forespørgselsoptimereren sandsynligvis vælge en plan med en Bitmap-operator for den anden forespørgsel, men ikke for den første. Hvorfor? Svaret ligger i selektivitet. Optimereren vurderer konstant omkostningerne ved forskellige strategier. For at en Bitmap-operator skal være nyttig, skal gevinsten ved at filtrere rækker overstige omkostningerne ved at bygge selve bitmappet. I det andet tilfælde vurderer optimereren, at filteret (Progr >= 501) er tilstrækkeligt selektivt til, at det kan betale sig at investere i at bygge et bitmap for at eliminere et stort antal rækker fra TabB tidligt i processen.

Hvordan fungerer Bitmap-operatoren i detaljer?

Processen kan opdeles i to hovedfaser: bygge-fasen og probe-fasen.

Is a 'bit-wise complement operator for not' in Java?
The language specification #4.2.2 defines "~" as 'the bitwise complement operator'. There is no such thing in Java as a 'bit operator for NOT'. @lh3: No. It's a one's complement operator in both C and C++. You are actually quite close. Yes, this is absolutely correct when we're talking about one bit.

Bygge-fasen: Oprettelse af bitmappet

Denne fase sker på den side af joinet, der kaldes "build side", hvilket typisk er den mindre tabel (TabA i vores eksempel). Processen er som følger:

  1. Systemet allokerer et array af bits i hukommelsen. Størrelsen af dette array afhænger af de værdier, der findes i join-kolonnen.
  2. For hver række i TabA tages værdien fra Progr-kolonnen.
  3. Denne værdi køres igennem en hash-funktion. En hash-funktion er en algoritme, der omdanner en input-værdi (som f.eks. tallet 501) til en anden numerisk værdi, der fungerer som et indeks i vores bit-array.
  4. Den bit, der svarer til det beregnede hash-indeks, sættes til 1.

Efter at have gennemgået alle relevante rækker i TabA, har vi nu et bitmap, hvor hver '1'-bit repræsenterer tilstedeværelsen af mindst én matchende værdi fra bygge-siden.

Probe-fasen: Filtrering med bitmappet

Nu flytter fokus til den større tabel, "probe side" (TabB i vores eksempel). Her bruges det netop oprettede bitmap til at filtrere rækker:

  1. Systemet begynder at scanne rækkerne i TabB.
  2. For hver række i TabB tages værdien fra Progr-kolonnen og køres igennem den nøjagtig samme hash-funktion som før.
  3. Systemet tjekker nu bit'en på det beregnede hash-indeks i bitmappet.
  4. Hvis bit'en er 0, betyder det, at der med garanti ikke findes en matchende værdi i TabA. Rækken bliver derfor kasseret med det samme og sendes ikke videre.
  5. Hvis bit'en er 1, betyder det, at der muligvis findes et match. Rækken får lov til at passere videre til den næste operator i eksekveringsplanen (typisk en Hash Join), som vil udføre den endelige verifikation.

Denne tidlige eliminering er ekstremt effektiv. I vores eksempel kunne det betyde, at i stedet for at sende 20.000 rækker videre til join-operatoren, sendes måske kun 2.000. Ofte vil man i eksekveringsplanen se en note om "IN ROW" optimering, hvilket indikerer, at denne filtrering sker meget tidligt og effektivt. Denne InRow-optimering er en nøglefaktor i ydeevneforbedringen.

Fordele og Ulemper

Som med de fleste teknologier er der afvejninger. Her er en oversigt over fordele og ulemper ved at bruge en Bitmap-operator.

FordeleUlemper
Markant ydeevneforbedring: Reducerer antallet af rækker, der skal behandles af efterfølgende, dyre operatorer som f.eks. joins.Overhead: Der er en omkostning forbundet med at bygge selve bitmappet. Hvis filteret ikke er selektivt nok, kan denne omkostning være større end gevinsten.
Effektiv i parallelle planer: Bitmappet kan nemt deles mellem parallelle tråde, så hver tråd kan filtrere sin del af dataene uafhængigt.Hukommelsesforbrug: Bitmappet optager plads i hukommelsen, hvilket kan være en faktor i systemer med begrænset RAM.
Reducerer I/O og CPU-belastning: Ved at fjerne unødvendige rækker tidligt, mindskes den samlede arbejdsbyrde for systemet.Ikke altid valgt: Forespørgselsoptimereren vælger kun denne strategi, når dens omkostningsmodel forudsiger en gevinst.

Ofte Stillede Spørgsmål (FAQ)

Hvorfor bruger min forespørgsel ikke en Bitmap-operator?

Hvis din eksekveringsplan ikke indeholder en Bitmap-operator, selvom du forventer det, er det fordi forespørgselsoptimereren har beregnet, at det ikke er den mest effektive strategi. Årsagerne kan være mange: datasættet er for lille, join-nøglen har lav kardinalitet (dvs. ikke-selektiv), eller omkostningen ved at opbygge bitmappet simpelthen overstiger den forventede gevinst ved at filtrere rækkerne.

Er en Bitmap-operator det samme som et Bitmap-indeks?

Nej, det er to forskellige ting. En Bitmap-operator opretter et midlertidigt bitmap i hukommelsen under kørslen af en specifik forespørgsel for at optimere et join. Et Bitmap-indeks er en permanent datastruktur, der gemmes på disken, og som bruges til hurtigt at finde rækker baseret på bestemte kolonneværdier, typisk i data warehousing-scenarier. De deler konceptet med at bruge bits, men deres formål og levetid er helt forskellige.

Hvad har dette med bitvise operationer at gøre?

Kernen i et bitmap er direkte manipulation af individuelle bits – at sætte dem til 1 eller 0. Dette er fundamentalt forbundet med de bitvise operationer, man finder i mange programmeringssprog. Et godt eksempel er bitwise NOT-operatoren (~) i sprog som Java. Mange tror fejlagtigt, at ~0 vil resultere i 1. Men i en 32-bit integer, som består af 32 nuller (000...00), inverterer ~-operatoren alle 32 bits til 1'ere (111...11). I det numeriske system, der kaldes to's komplement, repræsenterer denne bitstreng værdien -1. Dette eksempel illustrerer, hvordan computere arbejder på det laveste bit-niveau, hvilket er præcis den samme grundlæggende mekanisme, som Bitmap-operatoren udnytter til at skabe sine effektive datastrukturer. Forståelsen af bit-manipulation giver en dybere indsigt i, hvordan avancerede databaseoptimeringer fungerer internt.

Hvis du vil læse andre artikler, der ligner Bitmap-operatoren i SQL: En Dybdegående Guide, kan du besøge kategorien Teknologi.

Go up