This document describes how to use Symbian SQL trace data in Symbian platform applications.
Debugging and optimising database applications involves generic techniques which are not specific to Symbian implementation. This document does not aim to cover them all but illustrates ways of identifying common programming errors by means of SQL tracing.
Error traces
Error tracing identifies function leaves and panics in the client and server. These can occur for numerous reasons. One possible kind of error is KSqlErrSchema, which occurs when the database schema has been changed between a call to RSqlStatement::Prepare() and RSqlStatement::Exec() or RSqlStatement::Next().
Function entry traces
A function entry trace generates timestamps indicating the length of time a function took to return.
The function entry trace of RSqlStatement::Exec() with an SQL statement as argument can be used to identify which SQL statements are executing slowly. Statements can execute slowly for a great many reasons and tracing will not tell you why. A well known example is the inefficiency of storing blobs in a database table instead of storing the blobs elsewhere and their addresses in the database. The purpose of function entry tracing is to give you the data you need to identify cases of this kind.
The performance of RSqlStatement::Prepare() can also be impacted by inefficient SQL statements. For instance, in some cases, Prepare() runs in time O(N2) where N is the number of columns in the table. For values of N less than 100 the impact is not significant, but for values above 1000 the effect is very noticeable and data tables with a large number of columns are best avoided.
Key event traces
Key event traces identify events such as IPC calls, startup and close of the SQL server, and the number of full event scans performed by an RSqlStatement object.
Full table scans are particularly important as they are computationally costly and ought to be avoided. One reason for an unnecessary full table scan is the use of an expression in a WHERE clause instead of a column name. If you have a table with an integer primary key called id there is a big difference in performance between these SELECT statements:
SELECT name FROM table WHERE id=?
SELECT name FROM table WHERE id*1=?
Although the two statements are logically identical, the second statement is inefficient because the use of an expression id*1 disables optimisation and forces a full table scan for values satisfying it.
Another reason for a full table scan is incorrect use of indexes or simply failure to use them. The purpose of indexes is to search a table rapidly but there are pitfalls associated with their use. For instance, indexes will only be used if they contain 30 or fewer columns and they only speed up the evaluation of a WHERE clause if certain rules are obeyed.
A full table scan is also triggered by the use of the operator OR within a WHERE clause.