Welcome to Sign in | Help
in Search

problema cu Connection Timeout

Last post 12-20-2006, 1:15 AM by rremus. 4 replies.
Sort Posts: Previous Next
  •  12-19-2006, 1:58 AM 1369

    problema cu Connection Timeout

    Am o mare problema cu un sql a carui executie dureaza prea mult, asa ca vin cu 2 intrebari capitale la dumneavoastra. Mentionez ca foloesc VB din vs2005 CU SQL Server 2005 Developper edition

    1) Cum setez timeout-ul unei conexiuni sql ? Pe net am gasit urmatoarele metode, niciuna nu rezolva problema:
                    a) setarea Connection LifeTime sau/si Connection Timeout din stringul de conectare:
                                 dim sqlConn as new sqlconnection("Connection Lifetime=3000;    Connection Timeout=3000");
                                 sqlConn.Open();
                                  dim adapter as SqlDataadapter =   new     sqlDataAdapter("SELECT....",sqlConn);
                                  dim ds as new DataSet;
                                  adapter.Fill(ds,"ddd");
                   b) folosirea "sp_configure" in SQL server management studio:
                                  sp_configure 'remote query timeout',3000
                                   go
                                    reconfigure with override
                                  go
                        si
                                 sp_configure 'remote login timeout',3000
                                 go
                                 reconfigure with override
                                 go
                   c) in acelas minunat soft, la Tools->Options->Designers->Table and     Database Designers->Transaction time-out after si modificarea                  valorii de acolo
    2) cum pot selecta n linii dintr-un select incepand cu linia m (echivalentul lui LIMIT de la mySQL) ?. Din pacate rezultatul selectului e destul de mare(2,5 mil de linii) si solutia ar fi paginarea acestuia. 100 de linii cat are o pagina se intorc mult mai repede decat cele 2,5 mil.   Ce am gasit pe net urmeaza:
                   a) adapter.Fill(ds,index_start,numar_campuri,dataset). E ok metoda  pentru un numar mic de linii. E mult mai simpla decat celelalte, dar,                   din pacate eficienta ei e mica. Sql-ul se executa, sunt intoarse cele 2,5 milioane de linii, apoi sunt alese liniile care intereseaza
                    b) SELECT * FROM [tabel] TOP n WHERE [idtabel] NOT IN (SELECT  [idtabel] FROM [tabel] TOP m]. Merge foarte bine pentru primele linii  si foarte greu pentru ultimele linii (e evident si de ce)
                    c) WITH sql AS
                       {
                       SELECT *,ROW_NUMBER() OVER (ORDER BY [idtabel] as 'RowNumber'   FROM [tabel]
                       }
                      SELECT * FROM sql WHERE (RowNumber BETWEEN n AND m)
                      merge un pic mai greu pentru primele linii, dar ceva mai bine pentru  ultimele decat ultima metoda. Totusi dureaza intre 20 si 40 de                  secunde. Dezavantaj mare: merge foarte greu cu JOIN 
                      bineinteles am indexat baza, s-a observat o reducere la jumate a timpului de asteptare... dar am nevoie mai mult.

    Va rog, daca se poate, sa ma ajutati

    Mii de multumiri

  •  12-19-2006, 6:48 AM 1370 in reply to 1369

    Re: problema cu Connection Timeout

    Problema care o descrii (un batch SQL care dureaza 'prea mult') ar trebuii rezolvata prin a identifica de ce dureaza prea mult si apoi luate masurile necesare pentru a face ca acest SQL sa fie executat intr-un timp acceptabil. Masurile necesare depind, evident, de cauza problemei. Rezolvarea problemei prin abandonarea batch-ului daca dureaza prea mult nu rezolva nici o problema, doar cauzeaza timp/resurse/IO/CPU sa fie consumate degeaba pe server.

    In alta ordine de idei, raspunsul la intrebarea ta este ca trebuie sa setezi propietatea CommandTimeout pe obiectul SqlCommand care executa batch-ul. . Daca vrei sa folosesti SqlDataAdapter, atunci trebuie sa setezi propietatea CommandTimeout la obiectul care executa batch-ul pentru SqlDataAdapter: SqlDataAdapter.SelectCommand, SqlDataAdapter.InsertCommand, SqlDataAdapter.UpdateCommand sau SqlDataAdapter.DeleteCommand.

    Optiunile care le mentionezi sint:
    - "Connection Timeout": pentru a controla durata maxima cit clientul astepta deschiderea unei conexiuni noi, dupa cum este descris aici: http://msdn2.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring(VS.71).aspx . Nu exista o optiune "Connection Lifetime"
    - sp_configure 'remote login timeout' este durata folosita de SQL Server cind deschide conexiuni externe (linked servers, distributed queries)
    - VS options: sincer, habar n-am ce face aceasta optiune :)

    HTH,
    ~ Remus

     


    http://rusanu.com
  •  12-19-2006, 7:07 AM 1371 in reply to 1369

    Re: problema cu Connection Timeout

    2) cum pot selecta n linii dintr-un select incepand cu linia m (echivalentul lui LIMIT de la mySQL)

    Intrebarea aceasta apare destul de des, vezi http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=117121&SiteID=1 sau http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=359211&SiteID=1. In general solutiile recomandate folosesc ROW_NUMBER() intr-un mod sau altul (si eu as merge pe mina lui Umachandar).

    Parerea mea este ca modul acesta de paginare a unui resultset, foarte mult iubit de developerii de web, este problematic pentru ca neglijeaza accesul concurent si schimarile ce pot apare in baza de date intre selectarea 'paginilor'. De exemplu prima pagina contine record-urile r1, r2, ... r10. La selectarea paginii urmatoare, se astepata sa continue cu r11, r12, ... r20 dar, din cauza ca intre timp r8 a fost sters, 'pagina' intoarsa contine r12, r13, ... r21. Recordul r11 nu este returnat de nici o pagina. O solutie mult mai sigura este folosirea unui unique key si a clauzei TOP. La fiecare 'pagina' se cer primele N record-uri care au cheia mai mare decit ultima valoare din pagina anterioara. In general acest mod este si mai eficient, pentru ca planul de access poate localiza direct inceputul 'paginii' si continua scanarea de acolo, fara sa trebuiasca sa scaneze 'in gol' doar ca sa ajunga la primul record (ceea ce toate solutiile cu ROW_NUMBER() sau LIMIT fac).

    HTH,
    ~ Remus

     


    http://rusanu.com
  •  12-19-2006, 10:42 PM 1382 in reply to 1371

    Re: problema cu Connection Timeout

    Remus, iti multumesc frumos de sfaturi. Intr-adevar, metoda cu Timeout prezentata de tine a functionat si a rezolvat problema. De fapt, cea mai mare problema rezolvata a fost cea legata de Backup, care se face prin sql-ul "BACKUP TO.....". Orice ai face, baza de date ramane mare, iar un sql de backup dureaza destul de mult (in unele cazuri cu siguranta mai mult decat cele 30 de secunde)

    legat de cealalta problema, metoda e geniala prin simplitatea ei. Eficienta e maxima. Din 40 de secunde cat dura metoda precedenta, asta dureaza sub 1 secunda. Dar totusi mai am o intrebare. Exista vre-un SQL prin care pot selecta doar a n-a inregistrare (si numai a n-a)  ? Imi trebuie ca sa aflu id-ul liniei la care se afla prima inregistrare de pe pagina (in principiu vreau sa ramana paginarea). Daca nu se poate, probabil ca voi renunta la quick-jump-ul de pagini pagini si vor ramane doar controalele de prima pagina, pagina urmatoare, pagina precedenta, ultima data

     

    Inca o data, iti multumesc foarte mult de ajutor. Mi-a folosit  enorm.

  •  12-20-2006, 1:15 AM 1385 in reply to 1382

    Re: problema cu Connection Timeout

    Daca e vorba de BACKUP atunci intr-adevar nu ai prea mult cum sa-i reduci durata. Singura mea ingrijorare este ca faci backup din aplicatie. In general planul de backup trebuie lasat pe grija administratorului, separind responsabilitatzile de development (tu) fatza de cele de deployment (dba). Dar fara sa stiu detalii despre cum si unde se va folosi aplicatzia nu am cum sa judec, ce faci tu poate foarte bine sa fie corect (de ex. cind distribui o aplicatie care ruleaza pe 'auopilot', fara nici un fel de mentenantza, intr-un mediu unde nu exista dba). O sugestie ar fi sa te cosideri daca nu e mai bine ca aplicatzia ta sa foloseasca SQL Agent pentru a creea un plan de backup in loc sa ruleze comenzi de BACKUP direct din aplicatie. Un punct de pornire ar fi T-SQL sp_add_job sau SMO.

    Despre 'recordul nr. N', problema este ca nu exista un asemenea concept intro baza de date relationala. Nici ca teorie (algebra), nici ca practica (B-tree). Singurul mod de a gasi 'recordul nr. N' este ca pur si simplu incepi sa numeri recordurile si sa te opresti la N (de unde si toate solutiile cu RWO_NUMBER() OVER...).
    Dar asta nu inseamna ca totdeuna trebuie sa numeri 2 mil de recorduri ca sa afisezi pagina nr. 5000 :) Ma gindesc la cel putzin doua solutzii viabile:
    - navigarea cu un dictionar-index: in loc sa afisezi 'pagina 1', 'pagina 2' etc si sa lasi utilizatorul sa navigheze la 'pagina 100', potzi afisa un index: 'A', 'B', ... 'Z'. click pe 'M' duce utilizatorul la pagina care contine primul record care incepe cu 'M'. SQL-ul corespunzator este foarte eficient, pur si simplu SELECT TOP ... WHERE key >= 'M'. Similar cu o carte de telefon, potzi creea indexul cu mai multe nivele (indexul A-Z te duce la un al doilea index unde se pot selectiona paginile 'MAA-MZZ' s.a.m.d). Este o solutie eficienta si foarte 'user-friendly', oricine prefera sa caute in cartea de telefon la pagina 'POP' pentru Popescu, nu la 'Pagina 234, unde sint Popestii'. Dezavantajul este ca este destul de complex de implementat si codul in general este specific, nu poate fi refolosit generic pentru orice tabela
    - inserarea numarului de pagina in tabela. Pur si simplu fiecare record contine pagina in care trebuie afisat, setat la momentul cind record-ul este creat/schimbat. Atunci e extrem de simplu sa gasesti 'primul record din pagina N', penttru ca 'pagina N' este parte a cheii de index. Problema este ca acum aplicatia trebuie sa insereze valoarea corecta in coloana respectiva, o sarcina nu foarte simpla.

    HTH,
    ~ Remus


    http://rusanu.com
View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems