[C# ODBC] performance datareader

Pagina: 1
Acties:

  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:55
Ik zit hier met een vraagje over de odbcdatareader.

Ik zit hier met een Navision Native database. Deze is dus niet SQL based. Er is wel door microsoft een odbc driver geschreven. Deze driver kan niet alle functies uitvoeren dan een 'echte' odbc driver.

Helaas support deze driver geen .net datasets... Wat ik dus moet doen is:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
OdbcConnection myConn = new OdbcConnection(); 
myConn.ConnectionString = "DSN=test370;
//myConn.ConnectionString = "DSN=Sample C/ODBC 32 bit;"; 
try 
{
    //connectie maken
    Console.WriteLine("Connectie maken " + DateTime.Now);
    myConn.Open();
    Console.WriteLine("Connectie gemaakt " + DateTime.Now);

    string SQLstring = "SELECT * FROM Productiestuklijstregel";
    OdbcCommand myCommand = new OdbcCommand(SQLstring ,myConn);
    Console.WriteLine("Query uitvoeren " + DateTime.Now);

    //sql-query uitvoeren
    OdbcDataReader myReader = myCommand.ExecuteReader();
    Console.WriteLine("Query uitgevoerd " + DateTime.Now);
                
    //tabel aanmaken
    Console.WriteLine("Data laten zien " + DateTime.Now);
    DataTable dTable = new DataTable("List Records");
    
    //kolommen maken
    for (int fCount = 0; fCount < myReader.FieldCount; fCount++)
    {
        dTable.Columns.Add(new DataColumn(myReader.GetName(fCount)));
    }
    
    //data in tabel stoppen
    DataRow dRow;
    int i = 0; 
    while (myReader.Read()) 
    { 
        dRow = dTable.NewRow();
        for (int k = 0; k < myReader.FieldCount; k++)
        {
            dRow[k] = myReader.GetValue(k);
        }
        dTable.Rows.Add(dRow);
        i++;                    
    }
    
    //data laten zien
    dataGrid1.SetDataBinding(dTable,null);
    Console.WriteLine("Data laten zien klaar " + DateTime.Now);
    Console.WriteLine(dTable.Rows.Count + " records opgehaald");
    
    //connectie verbreken
    myConn.Close();


}
catch (Exception k)
{
    MessageBox.Show(k.ToString());
}


de DNS test370 is een testomgeving op t bedrijf. Ik heb ook een andere DNS en die wijst naar een lokale kopie van de database. (van vorige maand)

Als ik data ophaal van de lokale database:
Connectie maken 25-4-2006 8:54:28
Connectie gemaakt 25-4-2006 8:54:29
Query uitvoeren 25-4-2006 8:54:29
Query uitgevoerd 25-4-2006 8:54:40
Data laten zien 25-4-2006 8:54:40
'temp.exe': Loaded 'c:\windows\assembly\gac\system.xml\1.0.5000.0__b77a5c561934e089\system.xml.dll', No symbols loaded.
Data laten zien klaar 25-4-2006 8:54:51
8685 records opgehaald
uitvoeren van query duurt 11 seconden en 11seconden om de data te laten zien in een datagrid

Als ik data ophaal van de server database
Connectie maken 25-4-2006 8:57:34
Connectie gemaakt 25-4-2006 8:57:34
Query uitvoeren 25-4-2006 8:57:34
Query uitgevoerd 25-4-2006 8:57:39
Data laten zien 25-4-2006 8:57:39
'temp.exe': Loaded 'c:\windows\assembly\gac\system.xml\1.0.5000.0__b77a5c561934e089\system.xml.dll', No symbols loaded.
Data laten zien klaar 25-4-2006 8:58:52
9319 records opgehaald
uitvoeren van query duurt 5 seconden en data laten zien duurt 1min 13 seconden 8)7

Als ik dit dus zie betekend dat de Read functie op de server wordt uitgevoerd en dan 1 voor 1 alle records en 1 voor 1 alle velden verstuurd. Enorm slechte performance dus.

Wat ik me dus afvraag wat zie ik over het hoofd. Kan ik het via een andere manier doen :? Is er een manier om alle data ineens op te vangen?

[This space is for rent]


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

ODBC staat afaik bekend om zijn slechte performance.

Hoe de data verstuurd wordt hangt af van de applicatie. Eventueel kun je proberen met een netwerk monitor het gedrag te achterhalen (of gewoon met de windows performance monitor).

controleer, als dit mogelijk is, ook eens of het niet aan je query ligt door deze manueel uit te voeren.

ASSUME makes an ASS out of U and ME


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:40
HIGHGuY schreef op dinsdag 25 april 2006 @ 17:30:
ODBC staat afaik bekend om zijn slechte performance.
Heb je daar bronnen voor? Ik dacht altijd dat ADO trager was. (Maar ook daarvoor heb ik geen bronnen ;) )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • joopst
  • Registratie: Maart 2005
  • Laatst online: 01-10-2024
je hebt
code:
1
myConn.ConnectionString = "DSN=test370;
.

Voor elke verbinding naar de server moet die naam geresolved worden. En vast en zeker moet er ook iets van authenticatie gebeuren. Blijft de performance ook slecht als je een ip, username en password in de connectiestring zet ?

  • joopst
  • Registratie: Maart 2005
  • Laatst online: 01-10-2024
Volgens de msdn kan de DataAdapter een dataset vullen met een IDataReader.

De OdbcDataReader erft van DBDataReader welke IDataReader implementeert. Volgens mij kan je dus best een dataset vullen met jouw odbc connectie. Of mis ik nu iets ?

  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:55
HIGHGuY schreef op dinsdag 25 april 2006 @ 17:30:
...
Hoe de data verstuurd wordt hangt af van de applicatie. Eventueel kun je proberen met een netwerk monitor het gedrag te achterhalen (of gewoon met de windows performance monitor).

controleer, als dit mogelijk is, ook eens of het niet aan je query ligt door deze manueel uit te voeren.
1)
met execute query schiet het netwerk verkeer ff naar 14% voor paar seconden. Daarna bij het dataweergeven is dit weer 0-2%, maar is de cpu tijd 30-40%. 9100 records * velden is veel bewerkingen.

2)query manueel uitvoeren? Wat ik heb gedaan is met Business Objects en Crystal reports, die zijn beide ook >1minuut bezig.

Omdat ODBC sneller gaat met keys heb ik ook een ORDER BY gebruikt daarin een key van 2 velden die gespecificeerd zijn. Niet sneller. Ligt dus echt bij de reader.


via cfront (paar topics hierover gemaakt) gaat dit wel snel
velden aanmaken 26-4-2006 9:17:15
velden aanmaken klaar 26-4-2006 9:17:15
data in tabel zetten 26-4-2006 9:17:15
data in tabel zetten klaar 26-4-2006 9:17:28
9320 Records opgehaald.
nadeel is dat je zelf alles aan elkaar moet knopen :P (begeleider en ik zijn de enigste programmeurs op het bedrijf) Omdat de raporten soms veranderen kan ik dit niet hardcoded maken.

[This space is for rent]


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

farlane schreef op woensdag 26 april 2006 @ 08:56:
[...]


Heb je daar bronnen voor? Ik dacht altijd dat ADO trager was. (Maar ook daarvoor heb ik geen bronnen ;) )
ODBC is een generieke laag bovenop de andere specifieke lagen. Een extra laag is dus extra performance verlies. Bovendien raadt MS aan om bji hun SQL Server een DataReader te gebruiken aangezien die een native connectie kan opzetten die sneller is. (staat ergens onder optimizing ASP.NET in de MSDN)
PoweRoy schreef op woensdag 26 april 2006 @ 09:20:
[...]


1)
met execute query schiet het netwerk verkeer ff naar 14% voor paar seconden. Daarna bij het dataweergeven is dit weer 0-2%, maar is de cpu tijd 30-40%. 9100 records * velden is veel bewerkingen.

2)query manueel uitvoeren? Wat ik heb gedaan is met Business Objects en Crystal reports, die zijn beide ook >1minuut bezig.

Omdat ODBC sneller gaat met keys heb ik ook een ORDER BY gebruikt daarin een key van 2 velden die gespecificeerd zijn. Niet sneller. Ligt dus echt bij de reader.


via cfront (paar topics hierover gemaakt) gaat dit wel snel

[...]


nadeel is dat je zelf alles aan elkaar moet knopen :P (begeleider en ik zijn de enigste programmeurs op het bedrijf) Omdat de raporten soms veranderen kan ik dit niet hardcoded maken.
De bedoeling van het rechtstreeks uitvoeren van de query zonder ODBC of andere lagen is om te zien of de traagheid veroorzaakt wordt door een slechte query/DB of als de ODBC driver aan de basis ligt.

Bestaat er geen native driver voor die Navision ?

ASSUME makes an ASS out of U and ME


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:55
joopst schreef op woensdag 26 april 2006 @ 08:57:
je hebt
code:
1
myConn.ConnectionString = "DSN=test370;
.

Voor elke verbinding naar de server moet die naam geresolved worden. En vast en zeker moet er ook iets van authenticatie gebeuren. Blijft de performance ook slecht als je een ip, username en password in de connectiestring zet ?
Dit is helaas niet zo. Die DSN is de ODBC connectie die bij gegevensbronnen is gedefineerd. Toevallig heet die bron test370. Maar in de config staat ip etc ingevuld :)
En is toch maar 1 connectie :/ connectie openen, uitvoeren query, connectie sluiten:)
joopst schreef op woensdag 26 april 2006 @ 09:01:
Volgens de msdn kan de DataAdapter een dataset vullen met een IDataReader.

De OdbcDataReader erft van DBDataReader welke IDataReader implementeert. Volgens mij kan je dus best een dataset vullen met jouw odbc connectie. Of mis ik nu iets ?
DataSet wilde ik gebruiken maar dat ondersteunt de ODBC driver niet (handig). En btw de dataset doet eigenlijk precies hetzelfde als ik (handmatig lezen met read) alleen hij doet t onderhuids

[ Voor 5% gewijzigd door PoweRoy op 26-04-2006 09:43 ]

[This space is for rent]


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:55
HIGHGuY schreef op woensdag 26 april 2006 @ 09:31:

De bedoeling van het rechtstreeks uitvoeren van de query zonder ODBC of andere lagen is om te zien of de traagheid veroorzaakt wordt door een slechte query/DB of als de ODBC driver aan de basis ligt.

Bestaat er geen native driver voor die Navision ?
1) De Database software kan je niet gelijk een query uitvoeren, eerst een connectie dus via andere software. Als ik dit allemaal lokaal doe via de ODBC gaat het wel snel :) (even snel als de cfront)

Cfront is dus de native driver voor Navision, maar robuust en gebruiks vriendelijk is iets anders :P

[This space is for rent]


  • DaCoTa
  • Registratie: April 2002
  • Laatst online: 21:17
PoweRoy schreef op dinsdag 25 april 2006 @ 09:11:
Ik zit hier met een Navision Native database. Deze is dus niet SQL based. Er is wel door microsoft een odbc driver geschreven. Deze driver kan niet alle functies uitvoeren dan een 'echte' odbc driver.
Ik ben niet op de hoogte van Navision Native databases, maar hebben die zelf geen ODBC driver geschreven? Ik ken de andere MS ODBC drivers die standaard bij Windows meegeleverd worden en de meeste daarvan zijn - excuse my french - uberbrak, zowel in featureset als in performance. En als ze het zelf niet hebben, is er misschien een 3rd party die een ODBC driver geschreven heeft?

[ Voor 4% gewijzigd door DaCoTa op 26-04-2006 10:52 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:40
HIGHGuY schreef op woensdag 26 april 2006 @ 09:31:
ODBC is een generieke laag bovenop de andere specifieke lagen. Een extra laag is dus extra performance verlies.
Mja, maar voodat je vanaf ADO bij je database bent ga je ook door een heel aantal lagen volgens mij,

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:55
Navision was gemaakt door een deens bedrijf (:?) en is later overgekocht door Microsoft. Microsoft heeft later een ODBC driver gemaakt. Volgens de ODBC Guide van Navision:
C/ODBC has the functionality required for it to be used as a read/write data source.
The SQL conformance level is the CORE level.
The API conformance level is most of Extension Level 1. The driver doesn't support all the options defined as comprising ODBC functionality
Deze driver gebruik ik ook. Er zijn andere drivers ( op verschrikkelijke sites waarze hun product enorm veel aanprijsen ipv duidelijke specs te geven). Die drivers kosten 1000 euro etc :z Beetje veel geld voor een driver waar je de snelheidswinst niet van weet.

Ik gebruik Navision 3.70. Inmiddels is Navision 4.0 SP1 uit en die heeft een verbeterde ODBC functionaliteit. Helaas kan de 4.0 driver niet op de 3.70 database gebruikt worden. Bij komend nadeel is dat de database moet worden omgezet + al het maatwerk.
Daarom zoek ik uit hoe ik de ODBC kan versnellen

[ Voor 18% gewijzigd door PoweRoy op 26-04-2006 11:29 ]

[This space is for rent]


  • joopst
  • Registratie: Maart 2005
  • Laatst online: 01-10-2024
PoweRoy schreef op woensdag 26 april 2006 @ 09:20:
[...]
1)
met execute query schiet het netwerk verkeer ff naar 14% voor paar seconden. Daarna bij het dataweergeven is dit weer 0-2%, maar is de cpu tijd 30-40%. 9100 records * velden is veel bewerkingen.
Het lijkt erop dat het maken van die datatable de bottleneck is. Het kan dan dus idd liggen bij die reader, maar ook bij de 'server' die niet zoveel 'MB' in het geheugen kan oid. Ik vraag me alleen af hoe dat gemakkelijk te tetsen is.
Misschien door een ado db te maken met dezelfde tabel en query en kijken of het dan veel scheelt. Als het dan veel scheelt ligt het iig niet aan de server.

[ Voor 4% gewijzigd door joopst op 26-04-2006 11:58 . Reden: staat interessant ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:40
Btw, voor de meeste componenten kun je ook een array van objecten gebruiken, waarbij je de kolommen naar properties mapt.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:55
farlane schreef op woensdag 26 april 2006 @ 16:12:
Btw, voor de meeste componenten kun je ook een array van objecten gebruiken, waarbij je de kolommen naar properties mapt.
Zou je hier misschien een voorbeeld van kunnen geven? Snap niet echt wat je bedoeld.

[This space is for rent]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:40
Nou, ik begrijp uit je code dat de enige reden dat je een datatable wilt maken is omdat je em aan een datagrid wilt knopen.

Een datagrid kan als datasource ook een array van objecten gebruiken, waarbij de properties van een object in dat array mapt naar een kolom in het grid. semi code:

code:
1
2
3
4
5
6
7
8
9
10
class Foo
{
 property Blaat string
 property Mekker int
}

Foo() GridSource = .... // instantieren en pruttel

Grid.DataSource = GridSource;
Grid.DataBind();


Je moet nog wel het een en ander instellen aan properties van dat grid geloof ik, maar op deze manier krijg je een grid met de kolommen Blaat en Mekker

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:55
ah nu snap ik het :)

dat klopt een array van object koppelen. Alleen ik moet toch eerst een array van objecten hebben. Die haal ik via de odbc op en krijg de data terug via de datareader. Maar via de read gaat het veld voor veld af. Maar die read gaat dusdanig langzaam :). Denk niet dat het uitmaakt als ik de data in een row zet en die row van vasthaak aan de tabel. dan dat ik de data in een array met object gooi en die vasthaak aan de grid.

[This space is for rent]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23:40
Nou ja, voor het gebruiken van de datareader zal het geen verschil maken, maar ongetwijfeld wel voor het vullen van het grid plus je hoeft geen datatable te maken.

Is dus een beetje afhankelijk waar nnu precies het probleem zit, of het idd in de reader/netwerk zit of ergens anders.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Pagina: 1