3

In Delphi 4, we have one SELECT query which is fetching 3 Text type fields along with other required fields at a time using a TQuery component.
There are more than 1,000 records (which might increase in future).
This query consumes lots of memory. and I think due to this next query takes huge amount of time to execute.

I'm using BDE to connect to SQL-server.

I need to optimize the performance so that it won't take so much time. Please advice.

Johan
  • 74,508
  • 24
  • 191
  • 319
Dev
  • 629
  • 2
  • 9
  • 23
  • 4
    I'm fairly sure ADO wasn't introduced until Delphi 5 (perhaps even later than that). – LaKraven Dec 15 '11 at 06:58
  • TQuery is absolutely NOT the best way to do this! For one it's designed for the Borland Database Engine, which is prehistoric – LaKraven Dec 15 '11 at 06:59
  • TQuery uses BDE, it is obsolete for a long time. You are better to upgrade first and use modern data access components (AnyDAC, UniDAC or dbExpress) – kludg Dec 15 '11 at 06:59
  • In terms of being able to answer your question, more details are required: 1) What Database Engine are you using? If it's Paradox/DBase... you're making a tragic mistake strait out the gate! 2) What is the Query doing? Is it just a SELECT, or is it a multi-criteria UPDATE? More info please! – LaKraven Dec 15 '11 at 07:00
  • 1) TQuery uses BDE, 2) It is just a SELECT query. – Dev Dec 15 '11 at 07:04
  • Have you set indices (does BDE support them? I don't know). Will be better to move from BDE to another db engine (e.g. Firebird embedded, did the same, very easy to move) – Manuel Rauber Dec 15 '11 at 07:21
  • @LaKraven: BDE + SQLLinks just pass the query text to the server and then fetches the data like ADO does. BDE + SQL Links is usually faster than ADO because of all that ADO COM code. BDE is deprecated, but now ADO is deprecated as well. MS is going back to ODBC. Anyway, if one is still using D4 he has no choice. Or the BDE or a third party library. – Mad Hatter Dec 15 '11 at 08:46
  • @MadHatter firstly, I never recommended ADO to begin with (I merely stated that it wasn't available in Delphi 4). Second, ADO uses ODBC if you give it an ODBC connection string... again, not advocating it, just saying to correct your false assertion! – LaKraven Dec 15 '11 at 09:25
  • @LaKraven: you wrote "TQuery is absolutely NOT the best way to do this! For one it's designed for the Borland Database Engine, which is prehistoric". For the matter, D4 is prehistoric as well. If TQuery is not "the best way", what is it? At least the OP didn't use a TTable. What should have the OP used? – Mad Hatter Dec 15 '11 at 15:32
  • @MadHatterThe OP should do some research and make an informed decision of his own as-to which non-deprecated database engine/connector to use. If the OP wanted us all to preach our personal favorite, he would have asked. Since he didn't, I expressed merely my concern that the use of the seriously-deprecated BDE will certainly hamper performance and efforts to improve it. – LaKraven Dec 15 '11 at 16:26
  • @LaKraven: "deprecated" <> "not working". D4 is "deprecated" as well, being an old, unsupported version for which even third party libraries need to be old, probably unsupported ones, only compatible with old, unsupported database clients. It looks to me the BDE is the smallest issue here. The real issues with the BDE is using it as a database engine with Paradox/dBase files. When used just to access a RDBMS it does a decent job. –  Dec 15 '11 at 19:52

5 Answers5

2

You should consider some kind of Paging mechanism. do not fetch 1000 (or 1 million) records to the client, but instead use paging with SQL-server ROW_NUMBER() to get blocks of say 50-100 records per page.

so a query like:

SELECT id, username FROM mytable ORDER BY id

could look like this:

SELECT * FROM (
SELECT id, username, TOTAL_ROWS=Count(*) OVER(), ROW_NUMBER() OVER(ORDER BY id) AS ROW_NUM
FROM mytable 
) T1
WHERE ROW_NUM BETWEEN 1 AND 50

The ORDER BY field(s) should be Indexed (if possible) to speed things up.

kobik
  • 21,001
  • 4
  • 61
  • 121
  • Nice idea, but the app is using the `BDE` and `SQL Links`, which don't support `ROW_NUMBER()`, as far as I can recall. I don't think it existed in `SQL Server` at the time; the `BDE` has been deprecated for more than a decade now. – Ken White Dec 15 '11 at 23:55
1

If you use a TQuery, make sure that you use a local TField outside of the retrieval loop for faster process (the FieldByName method is somewhat slow).

You can try our freeware Open Source classes to access any DB engine.

It provides a direct access to MS SQL via OleDB, without calling the ADO layer.

It is very optimized for speed, and is Unicode ready, even on older version of Delphi. It has been tested on Windows XP, Vista, and Seven (including 64 bit).

It has a TQuery emulator: this is not a true TQuery as defined in the DB.pas unit, but a class with most of the same methods. And you won't need to work with all BDE classes and units. Drawback is that you can't use Delphi DB visual controls, but for a quick TQuery, it will do the work.

It has some unique features (like late-binding use for field access), which are worth considering.

It does not require any third-party library (like the BDE), and works from Delphi 5 up to XE2. I guess it will run under Delphi 4 also.

You can download and ask for support in our site.

Arnaud Bouchez
  • 42,305
  • 3
  • 71
  • 159
0

To reduce the time (depending on data) we can use DATALENGTH in a query.

like

DATALENGTH(TEXT) <> 0

This will not load records having no value in TEXT field.

Dev
  • 629
  • 2
  • 9
  • 23
0

Really fetching TEXT column values takes the time and takes the memory.

To speedup fetching, exclude TEXT columns from the SELECT list. And fetch them using an additional query by a record primary key and only when you really need their values.

To reduce memory usage do as above, use Unidirectional query or bove.

da-soft
  • 7,670
  • 28
  • 36
-2
  • Which field types did you define? If they are large, they will take up memory, there's little you can do about it. You may try different libraries, some are smart enough to allocate only the actual size of the field and not the declared one, other will always allocate the declared one, so if you have three fields of 4000 characters and 1000 records you will have 3 * 4000 * 1000 bytes allocated just for the text fields.
  • Do you need to load the whole dataset at once? Fetching just the needed data using a where condition and/or incremental fetching will help to reduce both memory and maybe execution time
  • If the query takes long to execute, you have to understand why and where. It could be the query execution time itself, it could be the time taken to transfer the result set to the client application. You need to profile your query to understand what is the issue actually, and take the proper corrective action. 1000 records is a very small dataset today, if it is slow there's something really bad.
  • Each database has subtle optimization differences. You have to study the one you're using carefully, and write the proper query for that database - after you designed the proper database.

Just changing the database components without determining that's exactly the cause is plainly stupid, and if the problem is elsewhere is just wasted time. BDE works well enough, especially if compared to ADO. And Microsoft is desupporting ADO as well, thereby I won't invest time and money in it.

Update: it would be interesting to know why this answer was downvoted. Just because ADO worshippers will have an hard time in the future, and they feel the need to hide the truth?

KEEP ON DOWNVOTING MORONS. YOU JUST SHOW YOUR IGNORANCE!

Mad Hatter
  • 772
  • 5
  • 5
  • "Microsoft is desupporting ADO" This is really interesting to me. Do you have any links or the likes that will confirm what you say here? This link kind of disagrees with you. http://msdn.microsoft.com/en-us/library/ms810810.aspx – Mikael Eriksson Dec 15 '11 at 09:47
  • http://blogs.msdn.com/b/sqlnativeclient/archive/2011/08/29/microsoft-is-aligning-with-odbc-for-native-relational-data-access.aspx – Mad Hatter Dec 15 '11 at 15:29
  • Thank you for the link but ADO is not mentioned in the blog post. SQL Server OLE DB provider is not the same as ADO. It is apparently perfectly fine to use ADO with SQL Server Native Client provider. – Mikael Eriksson Dec 15 '11 at 16:27
  • @Mikael: ADO is a "pointerless" wrapper of OLEDB. If you look at the architecture diagram at your URL, you can see ADO is built on top of OLEDB. Also it says "After SQL Server 2012, the SQL Server Native Client OLE DB provider will no longer be included in SQL Server Native Client." and "new applications should use the SQL Server Native Client ODBC driver". Microsoft **IS** desupporting ADO and going back to ODBC. –  Dec 15 '11 at 19:57
  • @ldsandon Thanks for you comment. This is not the appropriate place for a discussion about this but it is not enough info for me to suggest to management that we should redesign our n-tire architecture with something else then marshaled `recordset`s. As I read the posts it is the OLEDB provider for SQL Server that goes away. So far I have not found anything about the future of ActiveX Data Object. – Mikael Eriksson Dec 16 '11 at 07:02
  • A revenge downvote? At least, be not a moron and explain why you donwvoted. Once stackoverflow was a great place, now it's full of small incompetent developers trying to pretend they're not. – Mad Hatter Dec 16 '11 at 09:04
  • @Mikael: I was sure it wasn't yours, because we were politely discussing the future of ADO. Anyway if the OLEDB provider goes away, how could ADO work? MS could change ADO to work with ODBC directly, but will they do? ADO was made for VB which could not call OLEDB directly, but now no .NET language needs it. If they remove support from their flagship database, will they keep it up to date for competitors' products? – Mad Hatter Dec 16 '11 at 12:05
  • 1
    @MadHatter - ADO is (at least what I believe) basically the recordset object. http://msdn.microsoft.com/en-us/library/windows/desktop/ms681510%28v=vs.85%29.aspx And that can exist without the SQL Server OLEDB provider. You can for example use MSDASQL.1 which is the OLEDB provider for ODBC Drivers. So... before I can act on the fact that ADO is going away I need something more. I agree it's old or rather not up to date. You will for instance run into trouble using SQL Server Native Client with ADO and columns with the XML data type. The MDAC driver handles that by treating XML as ntext. – Mikael Eriksson Dec 16 '11 at 12:28
  • "ADO gives developers a powerful, logical object model for programmatically accessing, editing, and updating data from a wide variety of data sources **through OLE DB system interfaces**" (http://msdn.microsoft.com/en-us/library/windows/desktop/ms680928(v=vs.85).aspx). ADO is strongly tied to OLEDB. Although it is possible to use the same interfaces mapped to a different access layer, it is not clear if MS will do. The articles stating that ODBC will become the access layer seems to tell it won't. Of course ADO won't disappear suddendly, but I would be careful too for new projects –  Dec 16 '11 at 13:54