Selectarea înregistrărilor intermediare din setul rezultat - oracol pentru a cumpăra, oracle price - software

Apropo, vreau să informez pe toată lumea că astăzi traducerea celei de-a doua părți a cărții lui Tom Kait "Expert one-on-one: Oracle" sa încheiat. Ultimele fișiere de aplicații au fost trimise editorului în această dimineață.







Cum să afișați pagina de rezultate pe pagină?

Aș dori să selectez date după conectarea a trei tabele și sortarea după un câmp. Deoarece această interogare returnează aproximativ 100 de înregistrări, aș dori să rup setul de rezultate în 4 părți, fiecare cu câte 25 de înregistrări. Și aș vrea să numerotez înregistrările. Este posibil să faceți acest lucru în SQL * Plus?

Răspunsul lui Tom Kite

În Oracle8i, versiunea 8.1 - da.

Și asta e tot. În versiuni de până la 8,0 inclusiv nu va funcționa.

O cerere minunată. Voiam doar să mă asigur că îl înțeleg. Interogarea este executată de 4 ori și de fiecare dată când se modifică numerele de linie maximă și minimă. Corect?

Răspunsul lui Tom Kite

Da, valorile min și max se modifică pentru a obține diferite intervale de rânduri.

Și ce zici între?

Să revenim la vechea discuție despre diferența dintre interogare

Susțin că, din punctul de vedere al productivității, ele sunt identice. De fapt, planul de punere în aplicare a primei solicitări:

Pare mai repede decât

Dar, vă rugăm să rețineți că toți pașii planului nu se blochează. Prin urmare, nu contează care condiție este verificată mai devreme.

Răspunsul lui Tom Kite

Te rog, nu argumentati - puneti experimentele si dovediti (sa facem, intotdeauna fac asta).

Prima dvs. cerere, "în cazul în care rownum între 90 și 100" nu întoarce niciodată date. Această condiție este întotdeauna falsă, întotdeauna.

M-am dovedit deja, răspunzând la o altă întrebare (aparent, și a ta), că:

funcționează mai repede decât:

Sper să sperăm că veți chema. Totul este legat de modul în care COUNT (STOPKEY) este executat și de faptul că trebuie să efectuăm:

Apoi aplicați filtrul, în timp ce în primul caz selectăm primele 100 de linii ȘI TOATE.

Deci, hai să avem o masă neindexată:

(este obținut ca urmare a unei copii de trei ori a întregului conținut al reprezentării tuturor obiectelor). Voi face trei cereri pentru ea. Adevărul dvs. pentru a arăta că nu funcționează (nu returnează date), cel pe care cred că ați intenționat-o și opțiunea mea:

Acum, o cerere pe care o recomand tuturor:

GREAT diferență. Sunt gata să mă cert.

Declarații - nu au nevoie de nimeni.
Teste, experimente, statistici - Îmi plac, am nevoie de ele.

Mulțumesc, Tom. Am observat în cele din urmă că rownum este folosit într-o singură condiție. și în celălalt - rnum. și că acestea sunt diferite :-)

Cea mai bună soluție, pe care am venit-o eu:

De asemenea, funcționează mai lent și, evident, este mai puțin elegant :-(

Ne pare rău, dar nu văd diferența:

Răspunsul lui Tom Kite

Iată ce trebuie să utilizați.

execută interogarea dvs., selectează primele 100 de rânduri ale rezultatului și se oprește. Dacă YOUR_Request urmează să primească toate liniile înainte ca acesta să poată returna primul (de exemplu, include un grup de tip construct), atunci diferența în cazul dumneavoastră poate fi mică, dar este. Utilizați TKPROF. pentru a elimina timpul codului java al codului java (măsurarea timpului pe client în acest fel poate distorsiona foarte mult rezultatele).

Luați în considerare următorul exemplu:

Aici nu trebuie să luăm ultima linie înainte de a reveni pe prima - totul funcționează foarte "rapid"

Acum, să adăugăm funcția de agregare - acum trebuie să procesăm toate rândurile din tabel. Cu toate acestea, deoarece rownum este redat cât mai adânc posibil, puteți accelera munca din cauza anumitor optimizări

În cele din urmă, hai să o facem așa - nu luăm rownum cât mai adânc posibil, nu putem optimiza nimic și interogarea funcționează într-adevăr încet

În cele din urmă, depinde de tine. Pot să arăt doar că versiunea mea funcționează de mai multe ori mai repede. Alege.

În cazul tău, pot să presupun următoarele:

  • hz_parties este o vedere (recunoaște)
  • Această vizualizare este pentru a obține toate liniile înainte ca acestea să poată fi selectate din prima
  • Nu alegeți atât de multe linii (aproximativ o mie - toate se potrivesc în RAM)
  • Optimizarea rownum-ului în cazul tău nu dă mult - cu ajutorul tkprof poți afla exact ce dă.

În general, vreau să spun acest lucru:

Folosirea "unde rnum între a și b" va fi o eroare dacă puteți reda rownum într-o interogare internă și obțineți Phenomenal, în general, îmbunătățirea performanței. Dar să te aleagă.

Prima interogare prezentată mai jos funcționează de două ori mai rapidă decât a doua. Puteți explica motivul?

Răspunsul lui Tom Kite

De două ori mai repede. E ciudat. Nu știu ce înseamnă asta.

Pot să spun doar că (după corectarea cererilor dvs.) am obținut rezultate diferite. În cazul meu, când există aproximativ 1.000.000 de rânduri în tabela mare, am primit:

A doua interogare este mai eficientă decât prima.

Răspunsul lui Tom Kite

Dacă trebuie să alegeți lzhetsu la ontsu, aș sfătui să primesc setul rezultat într-o ordine diferită și alegeți mai aproape de început (modificați ordinea de sortare a datelor).

Da, ultimele linii N, în general, aleg mai mult decât primul N (nu întotdeauna, dar acest lucru poate fi de așteptat)

Am încercat să execut o astfel de interogare la o vedere ordonată, în care aproximativ 7000 de rânduri au valoarea eventseverity 64.

Dar, ca rezultat, am primit doar 234 de linii.

Dacă executați o subchetare

Primesc 500 de rânduri cu valori RNUM de la 1 la 500

Nu înțeleg de unde am greșit: - Recomandă ceva

Răspunsul lui Tom Kite

Urăsc prezentări cu ordin prin design. Adăugați o ordine după interogare. Pentru interogări complexe, ordinea datelor în vizualizări nu este neapărat susținută. Cel mai probabil, valoarea rownum-ului este pierdută undeva, dar în absența unui test reproductibil, nu pot spune exact ce se întâmplă.







Solicitarea dvs. este foarte bună și funcționează rapid în intervalul de la 100.000 până la 150.000 de rânduri, dar când încercați să preluați rânduri după 500.000, funcționează mai mult de un minut.

când este executat cu valorile 150001 și 150010, dă următorul rezultat și planul

Și atunci când sunt executate cu valorile 1000001 și 1000010, rezultatul și planul sunt prezentate mai jos:

Este posibil să se accelereze procesul de obținere a ultimelor linii?

Poate este mai bine să adăugați o comandă prin DESC construct și să obțineți prima pagină?

Eu folosesc în mod activ interogarea dvs. atunci când lucrați cu o bază de date, citind 1000 de intrări. În cazul în care 100.000 de înregistrări (acest lucru este destul de normal, ca utilizatorii să-mi spui :-)), un eșantion din primele 1000 de linii durează 50 de secunde :-(. (Server care rulează pe sistemul de operare Solaris, iar interfața JDBC este utilizată pentru a accesa baza de date). Trebuie să sorteze (comanda de) una dintre cheile primare.Could vă sfătuiți cum să îmbunătățiți performanța în acest caz.

Răspunsul lui Tom Kite

Utilizați acest instrument (sql_trace + TIMED_STATISTICS) pentru a obține planul de executare a interogării, numărul de rânduri procesate în fiecare etapă a planului și începeți acordul pe baza acestor informații.

Este posibil să fie necesară efectuarea optimizării în modul FIRST_ROWS.

Apropo, de ce 1000 de linii, - 25 sau 100 vor fi mai ușor de înțeles. Dar, în orice caz, cel mai probabil trebuie să sortați de fiecare dată 100.000 de linii. De asemenea, verificați dimensiunea dimensiunii sort_area.

Sunt cursorii cu defilare (9.2) disponibile în pl / sql și jdbc, sau doar în pro c / c ++?

Dacă nu, când va apărea această caracteristică în pl / sql?

Răspunsul lui Tom Kite

Ele sunt în jdbc.

Nu-mi pot imagina situația în care sunt necesare / de dorit în plsql. Acestea sunt utile pentru conexiuni într-un mediu client / server atunci când trebuie să vizualizați pagina de pagini setată după pagină, dar plsql nu este proiectat pentru acest mediu - rulează pe server. Presupunem că acest lucru se va face de către client (de exemplu, formulare sau jdbc). Când trebuie să reveniți la rândurile procesate în procedura stocată?

Cum se poate returna un set n din fiecare grup de înregistrări printr-o cheie, de exemplu, pentru astfel de date.

Vreau să reintroduc două înregistrări din fiecare grup în domeniul magazinului - două înregistrări pentru fiecare magazin.

va da rezultatul dorit.

Am decis să realizez un studiu suplimentar al abordării tale. Și dacă cineva vrea să obțină înregistrări de la M-a la N-ul Dept. nu de la Emp:

Ei bine, acest pește poate fi prăjit într-un mod diferit.

Funcțiile analitice - aceasta este puterea:

Când am încercat să pun în aplicare una dintre metodele tale, am avut probleme.

Vedeți următorul cod:

Am rezolvat această problemă prin interogarea șirului (OPEN out_cvGenric FOR 'select * din.') Și specificând clauza USING. Totul funcționează perfect.

Care este motivul acestei erori?

Consultați următorul cod. Aceasta este implementarea reală a metodei dvs. în PL / SQL:

În codul de mai sus, interogarea este plasată într-un șir, procedura a fost compilată cu succes. Dar când sunați, există erori.

Dacă ștergeți condiția "tire.tire_date>: ReportFromDt și tire.tire_date <:ReportToDt " из конструкции WHERE. запрос работает нормально и дает результаты. Если в запросе указаны даты, все ломается.

Apropo, această paginare în procedura stocată va facilita în mare măsură funcționarea serverului de aplicații. Dar, din păcate, nu pot rezolva a doua problemă.

Ai putea sugera o soluție?

Răspunsul lui Tom Kite

aceeași problemă și aceeași soluție în versiunea 8i și versiunile anterioare este dinamic SQL sau vizualizare.

2) De ce credeți că este o idee foarte, foarte rea. În primul rând, răspunsul se poate schimba și schimba (sensul dvs. este doar "presupunerea"). În al doilea rând, este cel mai simplu mod de a porni sistemul la o oprire completă. "O, întotdeauna fac același lucru și atât de mult timp". Este timpul să crească productivitatea mașinii la jumătate.

Aveți o eroare în operatorul sql. Am văzut imediat două probleme:

ȘI ORDINEAZĂ - aici expresii după și nu suficient.

În al doilea rând, nu există suficientă pereche de modificări asociate. În lista de utilizare, există cinci variabile și trebuie să legeți 7.

Problema nu este în datele - cererea este greșită.

Sfat (am găsit aceste erori) - copiați interogarea la sqlplus. înlocuiți interogarea globală cu '' și executați-o după variabila comenzilor:

Acum este clar unde este eroarea.

Paginare când căutați în câmpuri diferite

Răspunsul lui Tom Kite

YOUR_Request poate fi formulat ca un sql dinamic.

De fiecare dată când efectuați o căutare pe site-ul asktom exact așa cum se procedează. Dinamic, plus focalizare cu rownum.

Sunt un ADB și uneori întâmpin probleme cu ajutorul aplicațiilor web.

Dezvoltatorii de aplicații web mi-au cerut să pun în aplicare livrarea de la o pagină la alta, deoarece informațiile despre starea nu sunt salvate atunci când sunt conectate.

Doresc să execut interogarea o singură dată, dar a trebuit să creez ceva de genul următor, ceea ce conduce la re-parsare, re-executare și re-eșantionare pentru fiecare pagină:

1) Din câte știu, de fiecare dată când se întâmplă acest lucru, există o reanalizare, re-executare și repetare a datelor. Valorile variabilelor de legare sunt salvate și incrementate pentru fiecare pagină a aplicației. Este o abordare bună?

2) Nu va fi mai bine să returnați întregul set (cu optimizarea first_rows)?

3) Cum să implementați acest lucru?

4) Folosind cea de-a doua abordare, este posibil să organizăm un tip de conducte, astfel încât rândurile să fie returnate cererii treptat dintr-o singură interogare, dar nu toate dintr-o dată - tabelul este prea mare.

Răspunsul lui Tom Kite

1) Da, și eu fac asta. Nu există o conexiune și o activitate constantă atât în ​​mediul client-server, cât și în ce se poate face.

Eu personal fac din nou o parsare (soft) pentru fiecare pagină, decât voi susține o conexiune fizică separată (cu toate resursele corespunzătoare) pentru fiecare utilizator în cazul în care vrea să se uite la următoarea pagină.

2) și veți primi 500 de linii, iar utilizatorul se va uita la primele 10 și nu va merge niciodată la a doua pagină. Deci, ai efectuat de 50 ori mai mult I / O (LIO) decât ai nevoie? Cel mai probabil, de 40 de ori mai mult decât ai nevoie vreodată (10 pagini de străini, iar utilizatorul nu va accesa NICIODATĂ pagina 11).

4) Aceasta ar însemna o întoarcere la arhitectura client / server, cu o conexiune permanentă, devorând o mulțime de resurse de mașină chiar și atunci când nu este utilizată.

Tocmai am schimbat multe coduri, eliminând toate eșantioanele (*) înainte de a rula interogarea reală - mi-a luat-o de la dezvoltatorul anterior.

Unele argumente în favoarea acestui lucru am auzit de la un dezvoltator web (PHP). Tocmai am schimbat totul și l-am lăsat pe utilizatori să decidă dacă aceștia preferă performanțe mai înalte decât informații inutile. Ghici ce au ales!

Ceea ce lipsește este linia "rezultate 1-10 din aproximativ 500" - ar fi utilă. Utilizatorul ar dori să știe dacă numai câteva înregistrări stânga - atunci ar trebui să mergeți la pagina următoare, sau există mii, deci cel mai bine este de a preciza criteriile de căutare.

Știu că componenta Oracle Text permite astfel de lucruri, dar nu poate fi inventat ceva în Oracle "standard"? Pentru a utiliza Oracle Text, trebuie să rescrieți foarte mult în sistem.

Puteți selecta o linie de date din aplicația 21. Dacă cursorul returnează înregistrările 10-20, puteți afișa pe ecran (de exemplu) ">> cel puțin încă 7 linii" și dacă reveniți 21, dați ">> cel puțin 11 linii".


Ce lipsește este linia "rezultate 1-10 de aproximativ 500"
.

Dacă utilizați Oracle Text (așa cum fac în site-ul meu), atunci există funcții corespunzătoare.

Dacă utilizați optimizatorul de costuri pentru serverul de cost 9i, puteți obține un număr aproximativ de rânduri care vor returna interogarea în vizualizarea v $ sql_plan.

Expunerea paginată într-un mediu web

Mai jos este codul (specificația și corpul) al pachetului de lansare pe care îl vom folosi în mediul web. Pot fi îmbunătățite?

Da, băiete, ceva e în neregulă cu tine.

a) Continuați să nu utilizați variabilele de legare. Cea mai bună metodă de a șterge orice aplicație.

b) scrieți un cod procedural în cazul în care un operator sql este ENOUGH.

c) Această prelucrare procedurală se efectuează pe linie.

d) puneți datele în tabelul temporar dintr-un motiv foarte neînțeles.

e) Considerați numărul total de linii unul câte unul - în răspunsul anterior este scris că mă gândesc la această abordare (nu accept în principiu).

Dacă toate acestea sunt corectate, obținem:

Este această procedură folosită pe site-ul dvs.?

Dacă legați variabilele într-o sesiune și pentru conexiunea http, informații despre starea nu sunt acceptate, cum transferați datele?

Răspunsul lui Tom Kite

Da, aceasta este procedura pe care este folosit.

Câmpurile ascunse, cheile sunt de asemenea potrivite.







Trimiteți-le prietenilor: