views:

195

answers:

2

Let's say we have a [Valuations] table containing several values per date and per fund:
-FundId
-ValDate
-Value1
-Value2...

The Primary key is obviously FundId+ValDate.
I have also indexed the ValDate field since I often query for values on a specific date.

My question is: should I also create a specific index for the FundId, or is MsAccess clever enough to use the Primary key when querying on a specific FundId ?

+1  A: 

No need to put an index on the FundId column. Access is intelligent enough to use the PK under the situation you described.

BTW, is FundId unique? If so, there is no need to include ValDate as well.

Randy Minder
This is actually fairly well-known, and follows from the fact that the PK is a clustered index, and thus written in the order of the first column. Keep in mind, though, that if you have defined relational integrity between the 2nd column of your PK and the PK of another table, Jet/ACE creates a hidden index, so in that case, you don't need to create an index, because it will just duplicate the hidden index that Jet/ACE creates for RI purposes.
David-W-Fenton
No need to create an index but it doesn't hurt either by taking up any more room.
Tony Toews
@David W. Fenton: "if you have defined relational integrity between the 2nd column of your PK and the PK of another table, Jet/ACE creates a hidden index" -- you should be aware that you can specify `NO INDEX` when creating the `FOREIGN KEY` via SQL DDL in ANSI-92 Query Mode.
onedaywhen
@onedaywhen: that's one I didn't know. I have always wished it could be turned off as the default in the Access UI, since it just feels wrong to me to not have all the actual indexes show up in the table designer.
David-W-Fenton
@Tony Toews: I think it's better to not have extra indexes, since there's a limit of 32 per table. I've never bumped up against that myself, but I've seen cases where it came close.
David-W-Fenton
+2  A: 

The Primary key is obviously FundId+ValDate

In which order? And how do you access your data?

The Access Database Engine uses the PRIMARY KEY as the clustered index. If you did this

PRIMARY KEY (FundId, ValDate)

then you will get a different order on disk than if you did this

PRIMARY KEY (ValDate, FundId)

[In case you didn't use SQL DDL to create the PRIMARY KEY, perhaps someone could step and tells us how to specify the order of the columns in the PK when using the Access GUI. Thanks.]

The order of columns in the clustered index is important because it defines the one and only physical index for the table, your uber index as it were.

(ValDate, FundId) will favour BETWEEN (or equivalent) predicates or GROUP BY on ValDate e.g. date range queries returning multiple funds.

(FundId, ValDate) former may favour fund specific queries ... or may encourage page locks, depending on how the values are generated....

You should by now be getting the impression that with performance issues is there are many variables involved: how the PK was defined, the generation of the key values, how often you compact the file, your locking strategy (e.g. page level or row level?), high or low activity environment, etc. Not to mention the nature of the queries you run against the table (e.g. by date or by key?)

are you sure Access supports clustered indexes ?

Sure and here are some salient articles on MSDN:

New Features in Microsoft Jet Version 3.0 "Compacting the database now results in the indices being stored in a clustered-index format. While the clustered index isn't maintained until the next compact, performance is still improved. This differs from Microsoft Jet 2.x where rows of data were stored the way they were entered. The new clustered-key compact method is based on the primary key of the table. New data entered will be in time order."

Defragment and compact database to improve performance in Microsoft Access "If a primary key exists in the table, compacting restores table records into their primary key order. This provides the equivalent of Non-maintained Clustered Indexes, and makes the read-ahead capabilities of the Microsoft Jet database engine much more efficient... Query speed will be enhanced significantly, because they are now working with data that has been rewritten to the tables in contiguous pages. Scanning sequential pages is much faster than scanning fragmented pages."

How To Optimize Queries in Visual Basic "This article assumes that you are using the Microsoft Jet database engine... As your database grows, it will become fragmented. Compacting writes all the data in a table into contiguous pages on the hard disk, improving performance of sequential scans."

Information about query performance in an Access database "When you compact your database you can speed up queries. When you compact your database, the records of the table are reorganized so that the records reside in adjacent database pages that are ordered by the primary key of the table. This improves the performance of the sequential scans of records in the table because only the minimum number of database pages now have to be read to retrieve the records that you want."

onedaywhen
Thanks for these detailed remarks, onedaywhen. But are you sure Access supports clustered indexes ?
iDevlop
yes, see edit to answer.
onedaywhen
@onedaywhen Aftert re-reading my post, I think you were right in that the original quote didn't implicitly cover multiple-column indexes. I deleted the answer to avoid confusion.
Ben McCormack
Good collection of links. I once got shouted down in an Access newsgroup by suggesting random Autonumbers as a possible way of improving concurrency in a Jet database. Thoughts?
David-W-Fenton
(I'm assuming, of course, page-level and not record-level locking)
David-W-Fenton
"random Autonumbers as a possible way of improving concurrency in a Jet database... assuming, of course, page-level and not record-level locking" -- I think that is a very good point and one I hadn't considered until you said it a newsgroup three years ago (http://groups.google.co.uk/group/microsoft.public.access/msg/2e2a9412f8423203?hl=en) and please note the fact that I acknowledged it as a good point at least.
onedaywhen
@onedaywhen: are you citing your own response there? Or were you just picking a post in the thread?
David-W-Fenton
Citing my own response (Jamie Collins).
onedaywhen
@ David-W-Fenton: it seems very interesting idea and I will sure give it a try.
iDevlop