23. juli 2008 - 11:18Der er
14 kommentarer og 1 løsning
Optimer forespørgsel.
Hej,
Har en forespørgsel der kunne se således ud:
SELECT DISTINCT felt FROM tabel WHERE kunde_nr IN ('060139-3','060154-2','060155-9','060165-8','060148-4','060129-4','060152-6 ','060132-8','060145-0','060153-4','060124-5','060110-4','060115-3','060002- 3','060112-0','060138-5','060114-6','060159-1','060121-1','060151-8','061965 -0','060168-2','060156-7','060104-7','060140-1','060142-7','060161-7','06013 6-9','060107-0','060122-9','060167-4','060118-7','060106-2','060128-6','0601 25-2','060158-3','060137-7','060999-0','060111-2','060123-7','060144-3','060 150-0','060130-2','060116-1','060108-8','060109-6','060164-1','060162-5','06 0157-5','060166-6','060126-0','060103-9','060149-2','060134-4','060141-9','0 60160-9','060146-8','060163-3')
Hvor kundenr er taget fra en anden forespørgsel. Men ovenstående forespørgsel tager over 11 sekunder (vel og mærket når den ER cached). Der er små 13 mill poster i tabellen. Er der en måde at optimere forespørgelsen på? Ved godt der ikke er meget at arbejde med. DISTINCT er et must.
starter alle kundenumre i basen med 06 eller 060 så skal du måske overveje at lave et index som ikke er så skævt. Jeg mener at man kan vende et index om, men har aldrig prøvet det. Det vil nok give bedre performance
Det må da være muligt at joine på noget istedet - så du undgår den lange in-list?
Probelmet er at oracle bygger den op som en masse union all - 1 for hver værdi i din in-list.
Desuden ser den ud til at være dynamisk.. Hvor mange værdier regner du med at komme op på - du skal jo huske at der er et maximum på 1000 for en in-list.
pnielsen>> Har tænkt på det der med at joine, men den checker hvilke kundenr den kan tage i base1/schema1, tager kundenr fra base1/schema2 og laver til sidst forespørgslen i base2. Den kommer aldrig over 1000.
Kunne du evt. lave et matview baseret på de 2 tabeller komme af med din distinct tror jeg du kunne opnå en del.
Jeg sad også og tænkte på brugen af context index - men det hele afhænger lidt af casen(hvor tit det opdateres og data skal være tilgængeligt efter en opdatering)
For a query using the IN operator with a long IN-list of constant values, oracle reads every row of data from the table and compares each to all values listed in the IN-list of the IN operator. If the underlying table is large, full table scan can hit the performance. If the IN-list is quite small (only a few constant values) it transforms query and UNION ALL them to bring the results together.
SELECT order_number FROM orders WHERE status IN( ‘canceled’, ‘invalid’)
Next, Oracle transforms the query further as follows:
SELECT order_number FROM orders WHERE status = ‘canceled’ UNION ALL SELECT order_number FROM orders WHERE status = ‘invalid’
In such cases performance is good. But, if IN-list is very big you need to rewrite query.
Its not recommended to have very large IN-list, IN operator is to be used when you have very small number of inlist, IN operators used with large IN-list can often be rewritten using a join between the two tables instead.
hehe.. Gad vide om det er mig der har skrevet den artikel på metalink da jeg var hos Oracle - det er jo præcist det samme som jeg lige har skrevet for dig længere oppe :-)
Hej Paw, Nu har jeg fået lavet et databaselink, så man kan samle hele sql'en i én forespørgsel, men det hjælper ikke helt. Der er 2 problemstillinger: 1. kundenr i den base der er lavet link til er en char, bygget op på følgende måde (altid): 6 karakterer + '-' + 1 karakter. I den anden base er det en integer der kan indeholde 6 eller 7 cifrer. Er der 6 cifrer, skal der addes et 0 foran. 2. Jeg har fået svarstiden ned til 2 min. fra 8 min., men stadig ikke tilfredsstillende.
SELECT DISTINCT b.vareomrade FROM web_faktura_liste@wa_sgcap b WHERE b.kunde_nr IN( SELECT TO_CHAR('0'||SUBSTR(kundenr,0,5)||'-'||SUBSTR(kundenr,6,1)) AS kundenr FROM kmpv_kmpexnetkunder WHERE kundetype IN (SELECT SUBSTR(a.kundetyperegion,0,2) FROM schema2.wfak_kundenrregion a WHERE a.kundenr=9701731) AND region IN (SELECT SUBSTR(a.kundetyperegion,3,1) FROM schema2.wfak_kundenrregion a WHERE a.kundenr=9701731));
Hvad sker der hvis du laver en lokal kopi af web_faktura_liste i din db og bruger den istedet (kunne senere være et matview - hvis de system kan leve med data der kun refreshes nogle gange om dagen)?
Skal der laves noget fysisk i basen, skal der sendes et job afsted, derefter skal det gennem flere instanser osv osv. Det tager op til flere uger. Så der er i princip kun sql'en at arbejde med :(
Lige en ting Paw. Hvordan omskriver man ovenstående (25/07-2008 09:35:26) til en JOIN? Hvis du har tid altså ;o)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.