Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Producing database advice 2

Status
Not open for further replies.

jrbarnett

Programmer
Jul 20, 2001
9,645
GB
I work in an environment in which I am frequently asked questions about database platforms we support and provide general advice relating to troubleshooting queries and optimisation, as the in house guru.

I've started to put together a set of key points and advice for including on my intranet pages to give people a chance to try things out for themselves before approaching me.

So far, I've got:

To effectively troubleshoot slow running queries and database access code, you need to understand the data structure that the database uses and the tables/views that retrieve the data within the query.
The exact steps that you need to take will be specific to your application, but below are a few common problems I've seen that can be fairly easily resolved. The General points apply to any database engine.

1. There are nearly always multiple ways to write a query (eg using joins vs correlated subqueries). Try to write it in such a way that it can be covered by indexes rather than needing to go to the table directly. This is sometimes referred to as its sargability. (Sargeable is a term used by database professionals that refers to the Search Arguments of any given query).
2. Ensure that every table has a primary key and, if your database engine supports it, referential integrity between related tables. This will also help maintain data integrity within your application.
3. If you wrote the application (rather than written by an outsider and brought in), ensure the schema is normalised.
4. Only retrieve the data that you need to for a particular query. The more specific you can be with your criteria, the better the query optimiser in the database engine will be able to optimise. Be as direct as possible, specifying where fields are not equal to a particular value is almost certain to slow it down.
5. Avoid using "Select *" in queries. Instead, list the exact field names.
6. Minimise trips between the database server and the client. If you can retrieve everything you need in one retrieve then do it.
7. Don't over index. Whilst they are beneficial for searching and sorting, they slow down insert, update and delete operations. Producing the right balance of indexes to keep it running quickly without hurting performance is a matter of trial and error. Generally though, any fields that get used for searching or sorting will see some sort of benefit in being indexed.
8. Never assume that your data will be retrieved in a specific order, unless you include an ORDER BY clause in your query. Remember that SQL results are treated as a set, and the order of results is not important unless you force the database server to sort them.

Can anybody think of anything else worth including?
The people who generally ask me are partially database literate, ie they know some things about it (data comes from tables) but not as much as I do.

If anybody would like me to post the SQL Server and Access/Jet specific sections (plus another one for VB/VBA code in a different forum) I'm quite happy to.

John
 
That's a good list that should help the users work a bit more effectively. I'd add a couple of comments

Point 3 - add "normalised as far as is necessary". An unskilled user can totally destroy the performance of a system by normalising it to death.

Point 4 - add "list only the exact field names that you need. If you're not sure whether you need a field, leave it out and see if anyone complains."

Point 7 - add "any fields that get used for searching, sorting or relational links"

One last thought. Is their dialect of SQL case-sensitive? I seem to be forever reminding folk that "London" is not the same as "LONDON".

Geoff Franklin
 
Geoff

Thank you for your comments. I will amend my copy here.

The current SQL dialects we use aren't case sensitive (SQL 7, 2000 and Access/Jet MDB).

When time permits, I'm currently working on a MySQL one as well for the list, which is also used here, but am not nearly as familiar with that platform.

John
 
You might want to add something about not storing calculated values? This frustrates me to no end.

(unless it is some kind of Data Warehouse, but how often are your average users going to be troubleshooting one of those?)

I for one would like to see your Access and SQL Server specific sections. There are a few people around here who could benefit from having them branded on their arm. Ok, Ok, I will just print them a copy ;-)

Thanks for sharing.

Alex

Ignorance of certain subjects is a great part of wisdom
 
I've added to the main section "Always use the ANSI date format yyyy-mm-dd when dealing with databases, and use formatting on the client to display it as needed. This is the only format I have seen that consistently works properly across all database engines and client access programming models".

Alex:

Access/JET queries
1. Don't run VBA code via a query. This is the single biggest slow down factor I have ever seen. Rewrite the database access to perform small individual updates. If you need to perform complex record manipulation, it is often faster to use a VBA procedure to execute lots of smaller SQL statements. DoCmd.RunSQL (DAO) or CurrentProject.Connection.Execute (ADO) can be used to execute SQL statements directly.
2. Don't use recordsets for selecting data within code unless absolutely necessary. The domain functions (DLookup, DSum, DAvg, DCount etc) will suffice most of the time and be a lot faster.
3. If after evaluating all of this, your query is still slow, the JETSHOWPLAN feature can be used to view the query execution plan which can provide clues as to what is being done.
4. If you need to bring data in from an external source, use a pass through query via an ODBC connection rather than linked tables. This way, the Jet database engine will not try to to interpret the SQL code and you can use database server specific features.
5. Be very careful if switching between viewing totals and not viewing them (equivalent to a GROUP BY clause). If you view the totals, then remove them, any criteria that were previously in the WHERE clause get moved to the HAVING clause unless you are very careful. This forces the criteria to be evaluated after retrieval rather than retrieving only what gets selected.

SQL Server Queries
1. Embed your queries inside a stored procedure with parameters then execute the procedure. This code is compiled on first execution and run from the compiled copy which is far faster.
2. Running ad hoc queries via linked tables to an Access database is a performance killer (as SQL needs to keep locks on open tables/rows so other applications can't access them).
3. As much as possible, client access should be through ADO (for VB/VBA) or ADO.NET (for .NET tools). These both support the native client access protocols. DAO, used by Access 97, doesn't. Other programming systems will have their own systems for accessing database engines and it is worth researching them.
4. Access automatically puts a non clustered index on a foreign key relationship by default whereas SQL Server doesn't. You may want to manually add one.
5. The SQL Profiler can be used to generate a workload file to use with the Index Tuning wizard in Enterprise Manager. This can be very helpful in producing indexes beneficial for the queries that your applications run.
6. Don't use cursors within T-SQL code unless absolutely necessary. See if the query can be rewritten to use a set oriented operation.
7. Don't give your stored procedures names starting with sp_. This is because it is reserved for system stored procedures in the master database, and SQL server will search for them in the master database ahead of the current one.
8. Remember that SQL Server is just a Windows application implemented as a Windows service, so tools such as Performance Monitor and the Windows event logs can help diagnose problems with slow servers where it is the entire server rather than just one query that is running slowly.
9. Ensure that all objects within the same database are owned by the same account (normally dbo). Not doing so can cause significant slow down as well as permission problems. If you have queries that run across databases, they also need to be owned by the same account.

John
 
For anybody interested, I've posted the VB/VBA one in thread707-1323753 as its off topic for here.

John
 
Another one for the list. Especially relevant if your systems are world accessible:

Never return database server error messages straight to the client, especially if they are displayed straight on the screen.

Instead, write them to a table together with any other information you need (date/time, username, client application etc) and display a vague "A database error has occurred. Please try again" type message.
This helps hide errors that may otherwise be made available to anybody trying to break in (for example discovering the database schema or server details).

John
 
Never write a trigger that will only work properly if only one record at a time is inserted, deleted or updated. Sooner or later someone will need to make a global change.
If you can use a calculated field or a constraint instead of a trigger in SQL Server, do so, It will be more efficient. Never create a table no matter how small without a unique identifier.

And most of all - never ever make code changes on production (without first testing on development) becasue it's only a small change and it's urgent. Not only will you lose those changes the next time development code is posted to production (becasue you know that you won't remember to add it to development), but often this is when you accidentally delte a whole table or revise all the records instead of a subset, etc. The more urgent the request, the more important to test on development first.

Questions about posting. See faq183-874
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top