sql >> Database >  >> RDS >> Oracle

Waarom vertraagt ​​het controleren op null deze query?

De enige manier die ik kan bedenken om dat soort verschil in uitvoeringssnelheid te krijgen, zou zijn om (a) een index te hebben op field4 , en (b) hebben veel van lege datablokken; mogelijk van een hoogwaterlijn die zeer hoog is ingesteld door herhaalde directe padbelastingen.

De eerste query zou nog steeds de index gebruiken en presteren zoals verwacht. Maar aangezien null-waarden niet worden geïndexeerd, kan de index niet worden gebruikt om te controleren of or field4 is null staat, dus het zou terugvallen op een volledige tafelscan.

Op zich zou dat hier geen probleem moeten zijn, aangezien een volledige tabelscan van 7000 rijen niet lang zou moeten duren. Maar aangezien het is zo lang duurt, is er iets anders aan de hand. Een volledige tabelscan moet elk gegevensblok onderzoeken dat aan de tabel is toegewezen om te zien of ze rijen bevatten, en de tijd die het kost, suggereert dat er veel meer blokken zijn dan je nodig hebt om 7000 rijen vast te houden, zelfs met inline CLOB-opslag.

De eenvoudigste manier om veel lege gegevensblokken te krijgen, is door veel gegevens te hebben en vervolgens de meeste te verwijderen. Maar ik geloof dat je in een nu verwijderde opmerking op een eerdere vraag zei dat de prestaties vroeger goed waren en slechter zijn geworden. Dat kan gebeuren als u direct-path inserts , vooral als u gegevens 'vernieuwt' door ze te verwijderen en vervolgens nieuwe gegevens in de directe-padmodus in te voegen. Je zou dat kunnen doen met tussenvoegsels met de /*+ append */ wenk; of parallel; of via SQL*Loader. Elke keer dat je dat deed, zou het hoogwaterteken worden verplaatst, omdat oude lege blokken niet opnieuw zouden worden gebruikt; en elke keer zouden de prestaties van de query die op nulls controleert, een beetje verslechteren. Na veel iteraties zou dat echt gaan kloppen.

U kunt de datadictionary raadplegen om te zien hoeveel ruimte is toegewezen aan uw tabel (user_segments enz.), en vergelijk dat met de grootte van de gegevens die u werkelijk denkt te hebben. U kunt de HWM resetten door de tabel opnieuw op te bouwen, bijvoorbeeld door te doen:

alter table mytable move;

(bij voorkeur in een onderhoudsvenster!)

Als demo heb ik meer dan honderd keer een cyclus uitgevoerd om 7000 rijen in te voegen en te verwijderen, en vervolgens beide zoekopdrachten uitgevoerd. De eerste duurde 0,06 seconden (waarvan een groot deel overhead van SQL Devleoper is); de tweede nam 1.260. (Ik liep ook Gordon's, die een vergelijkbare tijd kreeg, omdat het nog een FTS moet doen). Met meer iteraties zou het verschil nog duidelijker worden, maar ik had geen ruimte meer... Ik deed toen een alter table move en voer uw tweede zoekopdracht opnieuw uit, wat vervolgens 0,05 seconden duurde.



  1. mysql:meerdere SELECT-instructies in Common Table Expression

  2. MySQL-query in Laravel Eloquent

  3. java.sql.SQLEException:Al gesloten

  4. PHP/MySQL-coderingsproblemen. � in plaats van bepaalde tekens