Databasteknik: Lösningar till teoriövning 8

Uppgift 1

a)

Nej, med så lite data (beroende på typ av databashanterare kanske upp till några tusen rader!) gör ett index ingen skillnad på söktiderna. Alla data får plats i samma diskblock eller "page" (några kilobyte), och det som tar tid i en normal, diskbaserad databas är att hitta rätt diskblock. Men om man räknar med att tabellen växer mycket i framtiden bör man skapa ett index på färgen:

CREATE INDEX Robotfärgsindex ON Robotar (Färg);
b) Ja, med så mycket data hjälper förmodligen ett index på färgen, som skapas på samma sätt som ovan.

c) Nej, då har kolumnen väldigt dålig selektivitet. Det går förmodligen fortare att läsa igenom hela tabellen från början till slut för att hitta alla blå robotar. Undantag om vi söker på någon av färgerna som en mycket liten andel av robotarna har.

Uppgift 2

Nej. De enda kolumner som nämns i frågan är Nummer och Färg, så det är bara just de kolumnerna som skulle kunna vara aktuella för att skapa index. Men nästan alla databashanterare skapar automatiskt ett index på en kolumn som man angett som en kandidatnyckel, antingen med PRIMARY KEY eller med UNIQUE, så vi ska inte skapa ett index på kolumnen Nummer. Att skapa ännu ett likadant index gör ingen nytta. Kolumnen Färg nämns i frågan, men bara i resultatet av sökningen och inte för att hitta rader, och vi har (normalt) ingen nytta av index på kolumner som bara är med i resultatet.

Följdfråga: Varför skapar databashanteraren automatiskt index på kandidatnycklar? (Två skäl!)

Följdfråga till följdfrågan: Varför skapar databashanteraren inte automatiskt index på alla kolumnerna?

Uppgift 3

Skapa index på de kolumner som används för att hitta rader, dvs för jämförelser med konstanter (som Robotar.Färg) eller i join-villkor (som Deltagare.Strid).

Däremot har vi (normalt) ingen nytta av kolumner som bara är med i resultatet, (som Robotar.Vikt). Om kolumnen redan har ett index (som primärnyckeln Robotar.Nummer) hjälper det inte att skapa ett till likadant.

Alltså:

Följdfråga: Primärnyckeln i tabellen Deltagare består av kolumnerna Robot och Strid (i den ordningen). Båda kolumnerna används i frågan. Varför ska vi skapa index på Strid men inte på Robot?

Följdfråga: Spelar det någon roll om det är få eller många olika datum på striderna, och om det är få eller många olika färger på robotarna?

Uppgift 4

Samma som i uppgiften ovan. Det är samma sökning, bara annorlunda formulerad. Databashanteraren har en frågeoptimerare som automatiskt väljer det snabbaste sättet att utföra sökningen, så alla tre SQL-frågorna kommer att köras på samma sätt, och ha samma nytta av vilka index som finns. Man säger att alla frågorna översätts till samma exekveringsplan.

Ibland förenklar man och säger att man ska skapa index på de kolumner som nämns i WHERE-villkoret, men då får man alltså se upp lite.

Men frågeoptimerare kan vara mycket komplexa, och de programmerare som skriver dem är människor, så det kan förstås hända att frågeoptimeraren inte är perfekt. Det kan alltså finnas databashanterare som kör frågorna olika snabbt. Och är vi verkligen säkra på att alla frågorna är exakt ekvivalenta?

Uppgift 5

Nej, man måste hämta alla vikterna för att räkna ut summan, så databashanteraren måste läsa igenom hela tabellen från början till slut, och har ingen nytta av att snabbt hitta individuella rader.

Följdfråga: Kan man göra på något annat sätt för att frågan ska gå snabbare att köra?

Uppgift 6

Ja, och även transaktioner som bara läser i databasen, och inte gör några ändringar, kan krocka med andra transaktioner. Vad händer till exempel om man ska summera alla beloppen på bankkontona, och så görs summeringen samtidigt som en annan transaktion flyttar pengar mellan två bankkonton? Summeringstransaktionen kanske läser det ena kontots belopp efter att pengarna har dragits, men det andra kontots belopp innan pengarna lagts dit, medan pengarna som flyttas så att säga befinner sig i luften. Då stämmer inte summan med hur mycket pengar som finns insatta på banken.

Uppgift 7

A: Man kanske lägger till en strid mellan två robotar, och så lägger man in en rad för striden i tabellen Strider, och den första robotens deltagande i tabellen Deltagare, men innan man hinner lägga till den andra robotens deltagande avbryts transaktionen av någon anledning. Då kommer det att se ut som om en robot har stridit utan motståndare.

C: Man kanske lägger till en strid med samma nummer som en som redan fanns i tabellen Strider. Då är primärnyckeln plötsligt inte unik längre. Eller så tar man bort en strid, men tar inte bort raderna i tabellen Deltagare som handlar om den striden. Då är referensintegriteten bruten, och det står i databasen att robotar har deltagit i en strid som inte finns.

I: Två strider har just avslutats, en mellan robot 1 och 2 och en mellan robot 3 och 4. Två olika forskare från forskningsgruppen AASS sitter vid varsin dator och lägger in de nya striderna i databasen. Båda forskarna ser att det högsta numret på en strid just nu är 3, så de försöker lägga in strid nummer 4. Redan där blir det en krock, men om vi antar att de nöjer sig med en enda, gemensam strid nummer 4, så lägger den första forskaren in att robot 1 och 2 deltog i strid 4, och den andra att robot 3 och 4 också deltog i strid 4. Då ser det ut som om det var en strid mellan fyra olika robotar, och inte två olika strider mellan två robotar vardera.

D: Robot 3 har bantat, och väger nu bara 900 kilo i stället för ett helt ton. Roboten lägger in sin nya vikt i databasen och avslutar transaktionen med COMMIT. Glad och stolt över sin lyckade bantning vill roboten visa sin nya vikt för sina robotkompisar, men då har ändringen inte sparats ordentligt, så i databasen står det fortfarande 1000 kilo. De andra robotarna skrattar, och robot 3 blir ledsen.

Uppgift 8

Det har olika dialekter av SQL. Varje databashanterare har sin dialekt. Mycket är likadant, men både detaljer och avancerade finesser kan skilja.

Vad som är "rätt" beror på vad man menar. Det finns en standard för frågespråket SQL, och enligt den heter det START TRANSACTION, men SQL-standarden skrevs långt efter att många av databashanterarna skapades. Standarden är en kompromiss där alla databashanterartillverkarna ville få med just sin databashanterares egenheter och finesser. Ska man använda en databashanterare måste man alltid lära sig hur man skriver i just den databashanteraren.

Uppgift 9

COMMIT avslutar en transaktion och ser till att de ändringar den gjort i databasen är permanent lagrade. ROLLBACK avslutar också transaktionen, men ser till att ingen av de ändringar den gjort i databasen finns kvar.

Uppgift 10

Att två eller flera transaktioner väntar på varandra i en cirkel, så ingen av dem kan köra vidare. Exempelvis kanske transaktion T1 låst dataobjektet D1 för att arbeta med det, och sen vill T1 arbeta även med dataobjektet D2, och försöker därför låsa det. Men en annan transaktion, T2, har redan låst D2 och arbetar med det, så T1 kan inte arbeta vidare utan får vänta på att T2 blir klar och låser upp D2. Sen vill T2 arbeta med dataobjektet D1, och försöker låsa det. Men D1 var ju redan låst av transaktion T1, så T2 kan inte arbeta vidare utan får vänta på att T1 blir klar och låser upp D1. Nu står T1 och T2 och väntar på varandra för evigt.

Jo, som programmerare behöver man bry sig om att det kan uppstå deadlock. Om mitt program skickar en transaktion till databashanteraren, och den transaktionen plötsligt kan avbrytas för att hindra deadlock, måste jag skriva mitt program så att det kan hantera det. Programmet kan försöka på nytt med samma transaktion, eller kanske bara ge ett felmeddelande till slutanvändaren. (Det måste man ändå göra, för det kan alltid uppstå fel: det kan bli strömavbrott på databasservern, nätverket mellan min dator och databasservern kan sluta fungera, och så vidare.)

Uppgift 11

En metod som räknar med att det för det mesta inte blir några krockar, och därför inte låser några data i förväg. Det kan förstås ändå bli krockar, så i slutet av transaktionen måste man kontrollera att det inte blev några.

Uppgift 12

Fråga 1:

nummer färg
1 gul
2 grön

Fråga 2:

nummer färg
1 gul
2 grön

Fråga 3:

nummer färg
2 grön

Fråga 4:

nummer färg
1 gul
2 grön

Fråga 5:

nummer färg
1 gul
2 grön

Fråga 6:

nummer färg
1 gul
2 grön
3 brun

Fråga 7:

nummer färg
1 gul
2 grön
3 brun

Fråga 8:

nummer färg
1 gul
2 grön
3 brun

Fråga 9:

nummer färg
1 gul
2 grön
3 brun
4 grön

Fråga 10 blir olika beroende på vilken metod för isolering som databashanteraren använder, men kan bli så här. Alternativt kan klient 2 stå och vänta i insert-kommandot.

nummer färg
1 gul
2 grön
3 brun
4 brun

Följdfråga: Vad kommer att hända sen, när det finns två olika banan nummer 4? Kan det bli olika beroende vilken metod för isolering som databashanteraren använder?


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 24 november 2022