tags:

views:

686

answers:

5

Are there general ABAP-specific tips related to performance of big SELECT queries?

In particular, is it possible to close once and for all the question of FOR ALL ENTRIES IN vs JOIN?

+2  A: 

I usually follow the rules stated in this pdf from SAP: "Efficient Database Programming with ABAP" It shows a lot of tips in optimizing queries.

Regards

franblay
+8  A: 

A few (more or less) ABAP-specific hints:

Avoid SELECT * where it's not needed, try to select only the fields that are required. Reason: Every value might be mapped several times during the process (DB Disk --> DB Memory --> Network --> DB Driver --> ABAP internal). It's easy to save the CPU cycles if you don't need the fields anyway. Be very careful if you SELECT * a table that contains BLOB fields like STRING, this can totally kill your DB performance because the blob contents are usually stored on different pages.

Don't SELECT ... ENDSELECT for small to medium result sets, use SELECT ... INTO TABLE instead. Reason: SELECT ... INTO TABLE performs a single fetch and doesn't keep the cursor open while SELECT ... ENDSELECT will typically fetch a single row for every loop iteration.

For large result sets, use a cursor and an internal table. Reason: Same as above, and you'll avoid eating up too much heap space.

Don't ORDER BY, use SORT instead. Reason: Better scalability of the application server.

Be careful with nested SELECT statements. While they can be very handy for small 'inner result sets', they are a huge performance hog if the nested query returns a large result set.

Measure, Measure, Measure Never assume anything if you're worried about performance. Create a representative set of test data and run tests for different implementations. Learn how to use ST05 and SM30.

There won't be a way to close your second question "once and for all". First of all, FOR ALL ENTRIES IN 'joins' a database table and an internal (memory) table while JOIN only operates on database tables. Since the database knows nothing about the internal ABAP memory, the FOR ALL ENTRIES IN statement will be transformed to a set of WHERE statements - just try and use the ST05 to trace this. Second, you can't add values from the second table when using FOR ALL ENTRIES IN. Third, be aware that FOR ALL ENTRIES IN always implies DISTINCT. There are a few other pitfalls - be sure to consult the on-line ABAP reference, they are all listed there.

If the number of records in the second table is small, both statements should be more or less equal in performance - the database optimizer should just preselect all values from the second table and use a smart joining algorithm to filter through the first table. My recommendation: Use whatever feels good, don't try to tweak your code to illegibility.

If the number of records in the second table exceeds a certain value, Bad Things [TM] happen with FOR ALL ENTRIES IN - the contents of the table are split into multiple sets, then the query is transformed (see above) and re-run for each set.

vwegert
+1 for the measure, measure :)
PATRY
Don't ORDER BY, use SORT instead. -- I don't get it. Why is ABAP server expected to be smarter than underlying DB server?
ilya n.
It's not smarter, it's just more scalable. You can easily plug in more application servers (processes or even hardware) if you need it, but if your database system runs into performance trouble, it can be difficult to upsize it...
vwegert
But the DB may have a lot more information than the app server (e.g. indexes). My recommendation was the other way around, i.e. let the DB as much work as possible. Your scalability point is well noted, though.
IronGoofy
You're absolutely right when it comes to processing the query itself. But sorting the result - personally, I'd leave that to the ABAP processor.
vwegert
+1  A: 

There are also quite extensive hints and tips in transaction SE30. It even allows you (depending on authorisations) to write code snippets of your own & measure it.

Unfortunately we can't close the "for all entries" vs join debate as it is very dependent on how your landscape is set up, wich database server you are using, the efficiency of your table indexes etc.

The simplistic answer is let the DB server do as much as possible. For the "for all entries" vs join question this means join. Except every experienced ABAP programmer knows that it's never that simple. You have to try different scenarios and measure like vwegert said. Also remember to measure in your live system as well, as sometimes the hardware configuration or dataset is significantly different to have entirely different results in your live system than test.

Esti
+1  A: 

This question will never be completely answered.

ABAP statement for accessing database is interpreted several times by different components of whole system (SAP and DB). Behavior of each component depends from component itself, its version and settings. Main part of interpretation is done in DB adapter on SAP side.

The only viable approach for reaching maximum performance is measurement on particular system (SAP version and DB vendor and version).

A: 

Another note: The "Avoid SELECT *" statement is true in general, but I can tell you where it is false.
When you are going to take most of the fields anyway, and where you have several queries (in the same program, or different programs that are likely to be run around the same time) which take most of the fields, especially if they are different fields that are missing.

This is because the App Server Data buffers are based on the select query signature. If you make sure to use the same query, then you can ensure that the buffer can be used instead of hitting the database again. In this case, SELECT * is better than selecting 90% of the fields, because you make it much more likely that the buffer will be used.

Also note that as of the last version I tested, the ABAP DB layer wasn't smart enough to recognize SELECT A, B as being the same as SELECT B, A, which means you should always put the fields you take in the same order (preferable the table order) in order to make sure again that the data buffer on the application is being well used.

Noah