sql >> Databasteknik >  >> RDS >> Oracle

Varför fördröjer sökningen efter null den här frågan?

Det enda sättet jag kan tänka mig att få den typen av skillnad i exekveringshastighet är att (a) ha ett index på field4 , och (b) har ett parti av tomma datablock; möjligen från ett högvattenmärke satt mycket högt av upprepade belastningar i direkt väg.

Den första frågan skulle fortfarande använda indexet och fungera som förväntat. Men eftersom nollvärden inte indexeras kan indexet inte användas för att kontrollera att or field4 is null skick, så att det skulle falla tillbaka till en fullständig tabellskanning.

Det i sig borde inte vara ett problem här, eftersom en fullständig tabellskanning av 7000 rader inte borde ta lång tid. Men eftersom det är tar så lång tid, något annat är på gång. En fullständig tabellsökning måste undersöka varje datablock som tilldelats tabellen för att se om de innehåller några rader, och den tid det tar tyder på att det finns mycket fler block än du behöver för att hålla 7000 rader, även med inline CLOB-lagring.

Det enklaste sättet att få många tomma datablock är att ha mycket data och sedan radera det mesta. Men jag tror att du sa i en nu raderad kommentar på en tidigare fråga att prestandan brukade vara OK och har blivit sämre. Det kan hända om du gör direktvägsinfogningar , särskilt om du "uppdaterar" data genom att radera den och sedan infoga ny data i direktvägsläge. Du kan göra det med inlägg som har /*+ append */ ledtråd; eller parallellt; eller genom SQL*Loader. Varje gång du gjorde det skulle högvattenmärket flyttas, eftersom gamla tomma block inte skulle återanvändas; och varje gång utförandet av frågan som kontrollerar nollvärden skulle försämras lite. Efter många iterationer skulle det verkligen börja stämma.

Du kan kontrollera dataordlistan för att se hur mycket utrymme som är tilldelat din tabell (user_segments etc.), och jämför det med storleken på den data du tror att du faktiskt har. Du kan återställa HWM genom att bygga om tabellen, t.ex. genom att göra:

alter table mytable move;

(helst i ett underhållsfönster!)

Som en demo körde jag en cykel för att infoga och ta bort 7000 rader med direkt sökväg över hundra gånger och sedan körde båda dina frågor. Den första tog 0,06 sekunder (av vilka mycket är SQL Devleoper overhead); den andra tog 1.260. (Jag körde även Gordon's, som fick en liknande tid, då den fortfarande måste göra en FTS). Med fler iterationer skulle skillnaden bli ännu mer markant, men jag fick slut på utrymme... Jag gjorde sedan en alter table move och körde din andra fråga igen, som sedan tog 0,05 sekunder.



  1. MYSQL Deduplicera och ta bort dubblettraden med minst data

  2. Hur man återställer mysql root-lösenord i MacOS

  3. 4 sätt att kontrollera om en tabell finns innan du släpper den i SQL Server (T-SQL)

  4. Försöker installera innodb memcached plugin MySQL5.6.17 på ubuntu 14.04