| Author |
Topic |
|
Mountain_Nerd
Starting Member
28 Posts |
Posted - 2007-09-24 : 16:03:18
|
I'm working on an address management system with a normalized db structure. I have a view that aggregates the various lookup tables into a "nice" address. The only unique aspect of the view is that it places a leading zero in front of the street name field for street names that are single-digit numeric (i.e. 5th St. becomes 05th St) for ordering purposes. When I run a query against the view, with or without a WHERE clause, performance is acceptable; however, once I introduce an ORDER BY clause, the query becomes very slow. I want to run the ORDER BY the field with the leading zeros (OBSTNAME), but I have even altered which fields the ORDER BY runs against, without any significant performance improvement.Any ideas? Thanks in advance!ChrisVIEW:ALTER VIEW [dbo].[v_ai_StreetZips]ASSELECT sz.StreetNameZipID, sn.StreetNameID, sp.Prefix, sb.BaseName, st.[Type], ss.Suffix, sz.ZipCode, RTRIM(LTRIM(ISNULL(sp.Prefix,'') + ' ' + sb.BaseName + ' ' + ISNULL(st.[Type],'') + ' ' + ISNULL(ss.Suffix,''))) AS FullName, CASE WHEN LEFT(sb.BaseName,1) IN ('1','2','3','4','5','6','7','8','9','0') AND SUBSTRING(sb.BaseName, 2, 1) NOT IN ('1','2','3','4','5','6','7','8','9','0') THEN '0' + sb.BaseName ELSE sb.BaseName END As OBSTNAME, sp.PrefixID, sb.BaseNameID, st.TypeID, ss.SuffixIDFROM ai_StreetNameZips szLEFT OUTER JOIN ai_StreetNames sn ON sn.StreetNameID = sz.StreetNameIDLEFT OUTER JOIN ai_StreetPrefix sp ON sn.PrefixID = sp.PrefixIDLEFT OUTER JOIN ai_StreetBaseNames sb ON sn.BaseNameID = sb.BaseNameIDLEFT OUTER JOIN ai_StreetTypes st ON sn.TypeID = st.TypeIDLEFT OUTER JOIN ai_StreetSuffix ss ON sn.SuffixID = ss.SuffixIDGOQUERY:DECLARE @streetnamezipid INT , @streetnameid INT , @prefix VARCHAR(2) , @basename VARCHAR(50) , @type VARCHAR(4), @suffix VARCHAR(2) , @prefixid INT , @basenameid INT , @typeid INT , @suffixid INT , @zipcode VARCHAR(5)Set @zipcode = '99999' SELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE StreetNameZipID = COALESCE(@streetnamezipid, StreetNameZipID) AND StreetNameID = COALESCE(@streetnameid, StreetNameID) AND Prefix = COALESCE(@prefix, Prefix) AND BaseName = COALESCE(@basename, BaseName) AND [Type] = COALESCE(@type, [Type]) AND Suffix = COALESCE(@suffix, Suffix) AND PrefixID = COALESCE(@prefixid, PrefixID) AND BaseNameID = COALESCE(@basenameid, BaseNameID) AND TypeID = COALESCE(@typeid, TypeID) AND SuffixID = COALESCE(@suffixid, SuffixID) AND ZipCode = COALESCE(@zipcode, ZipCode)-- ORDER BY OBSTNAME, [Type], Prefix |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2007-09-24 : 16:29:55
|
| Post all indexes and constraints for the table involved in the view.Tara KizerMicrosoft MVP for Windows Server System - SQL Serverhttp://weblogs.sqlteam.com/tarad/ |
 |
|
|
dinakar
Master Smack Fu Yak Hacker
2507 Posts |
Posted - 2007-09-24 : 16:36:23
|
| Are there any indexes on OBSTNAME, [Type], Prefix columns? Also if the record size is small you can do the ordering at front end.Dinakar Nethi************************Life is short. Enjoy it.************************http://weblogs.sqlteam.com/dinakar/ |
 |
|
|
Mountain_Nerd
Starting Member
28 Posts |
Posted - 2007-09-24 : 17:14:08
|
Here are the indexes... Interestingly, even if I perform an ORDER BY BaseName (which has a non-clustered index already), performance is still slow. I added non-clustered indexes to the Type and Prefix fields, to no avail.Here are the indexes and constraints:ALTER TABLE [dbo].[ai_StreetNameZips] ADD CONSTRAINT [StreetNameZipID_pk] PRIMARY KEY CLUSTERED ([StreetNameZipID] ASC)ALTER TABLE [dbo].[ai_StreetNameZips] WITH CHECK ADD CONSTRAINT [StreetNameIDZips_fk] FOREIGN KEY([StreetNameID])REFERENCES [dbo].[ai_StreetNames] ([StreetNameID])ALTER TABLE [dbo].[ai_StreetNameZips] CHECK CONSTRAINT [StreetNameIDZips_fk]ALTER TABLE [dbo].[ai_StreetNameZips] WITH CHECK ADD CONSTRAINT [ZoneSet_fk] FOREIGN KEY([ZipCode])REFERENCES [dbo].[ai_ZoneSet] ([ZipCode])ALTER TABLE [dbo].[ai_StreetNameZips] CHECK CONSTRAINT [ZoneSet_fk]ALTER TABLE [dbo].[ai_StreetNames] ADD CONSTRAINT [StreetName_pk] PRIMARY KEY CLUSTERED ([StreetNameID] ASC)ALTER TABLE [dbo].[ai_StreetNames] WITH CHECK ADD CONSTRAINT [ai_BaseNames_fk] FOREIGN KEY([BaseNameID])REFERENCES [dbo].[ai_StreetBaseNames] ([BaseNameID])ALTER TABLE [dbo].[ai_StreetNames] CHECK CONSTRAINT [ai_BaseNames_fk]ALTER TABLE [dbo].[ai_StreetNames] WITH CHECK ADD CONSTRAINT [ai_Suffix_fk] FOREIGN KEY([SuffixID])REFERENCES [dbo].[ai_StreetSuffix] ([SuffixID])ALTER TABLE [dbo].[ai_StreetNames] CHECK CONSTRAINT [ai_Suffix_fk]ALTER TABLE [dbo].[ai_StreetNames] WITH CHECK ADD CONSTRAINT [Prefix_fk] FOREIGN KEY([PrefixID])REFERENCES [dbo].[ai_StreetPrefix] ([PrefixID])ALTER TABLE [dbo].[ai_StreetNames] CHECK CONSTRAINT [Prefix_fk]ALTER TABLE [dbo].[ai_StreetNames] WITH CHECK ADD CONSTRAINT [Type_fk] FOREIGN KEY([TypeID])REFERENCES [dbo].[ai_StreetTypes] ([TypeID])ALTER TABLE [dbo].[ai_StreetNames] CHECK CONSTRAINT [Type_fk]ALTER TABLE [dbo].[ai_StreetPrefix] ADD CONSTRAINT [ai_StreetPrefix_pk] PRIMARY KEY CLUSTERED ([PrefixID] ASC)ALTER TABLE [dbo].[ai_StreetBaseNames] ADD CONSTRAINT [ai_StreetBaseNames_pk] PRIMARY KEY CLUSTERED ([BaseNameID] ASC)CREATE NONCLUSTERED INDEX [ai_StreetBaseNames_idx] ON [dbo].[ai_StreetBaseNames] ([BaseName] ASC)ALTER TABLE [dbo].[ai_StreetTypes] ADD CONSTRAINT [ai_StreetType_pk] PRIMARY KEY CLUSTERED ([TypeID] ASC)ALTER TABLE [dbo].[ai_StreetSuffix] ADD CONSTRAINT [ai_StreetSuffix_pk] PRIMARY KEY CLUSTERED ([SuffixID] ASC) |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-09-24 : 17:18:51
|
[code]ALTER VIEW dbo.v_ai_StreetZipsASSELECT sz.StreetNameZipID, sn.StreetNameID, sp.Prefix, sb.BaseName, st.[Type], ss.Suffix, sz.ZipCode, RTRIM(LTRIM(ISNULL(sp.Prefix, '') + ' ' + sb.BaseName + ' ' + ISNULL(st.[Type], '') + ' ' + ISNULL(ss.Suffix, ''))) AS FullName, CASE WHEN sb.BaseName LIKE '[0-9][^0-9]%' THEN '0' + sb.BaseName ELSE sb.BaseName END AS OBSTNAME, sp.PrefixID, sb.BaseNameID, st.TypeID, ss.SuffixIDFROM ai_StreetNameZips AS szLEFT JOIN ai_StreetNames as sn ON sn.StreetNameID = sz.StreetNameIDLEFT JOIN ai_StreetPrefix as sp ON sn.PrefixID = sp.PrefixIDLEFT JOIN ai_StreetBaseNames as sb ON sn.BaseNameID = sb.BaseNameIDLEFT JOIN ai_StreetTypes as st ON sn.TypeID = st.TypeIDLEFT JOIN ai_StreetSuffix as ss ON sn.SuffixID = ss.SuffixID[/code] E 12°55'05.25"N 56°04'39.16" |
 |
|
|
Mountain_Nerd
Starting Member
28 Posts |
Posted - 2007-09-25 : 10:37:59
|
Thanks for the WHEN sb.BaseName LIKE '[0-9][^0-9]%' THEN '0' + sb.BaseName hint. Much more elegant.After some careful teasing apart, I have been able to determine that the offending portion of the query is this portion of the WHERE clause:AND TypeID = COALESCE(@typeid, TypeID) The TypeID is the PK in the ai_StreetTypes table and a FK in the ai_StreetNames table. I rebuilt the indexes just to make sure that there were no issues. This did not help.Just to clarify, if this portion of the WHERE clause is commented out, the query takes less than 1 second. When used, the query takes 40 seconds. Although I think I could probably find a work-around, I really ought to figure out why this is so. Any ideas now that I've narrowed it down? This is quite frustrating. |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-09-25 : 10:45:38
|
Try this querySELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE StreetNameZipID = @streetnamezipidUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE StreetNameID = @streetnameidUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE Prefix = @prefixUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE BaseName = @basenameUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE [Type] = @typeUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE Suffix = @suffixUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE PrefixID = @prefixidUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE BaseNameID = @basenameidUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE TypeID = @typeidUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE SuffixID = @suffixidUNIONSELECT StreetNameZipID, StreetNameID, FullName, Prefix, BaseName, [Type], Suffix, PrefixID, BaseNameID, TypeID, SuffixID, ZipCode FROM v_ai_StreetZips WHERE ZipCode = @zipcode E 12°55'05.25"N 56°04'39.16" |
 |
|
|
Mountain_Nerd
Starting Member
28 Posts |
Posted - 2007-09-25 : 11:12:31
|
| Jeff...THANKS!!! That worked perfectly. I think you've made a convert of me... avoid CASE (and by proxy, COALESCE) in a WHERE clause! I read your blog posting and I can definitely see how using simple boolean logic like this would be more efficient, but I'm a little confused about why this would result in a query so horribly inefficient for only this table/field. The inefficient COALESCE performs acceptably for all the other fields. Any ideas? |
 |
|
|
aravindt77
Posting Yak Master
120 Posts |
Posted - 2007-09-26 : 00:15:30
|
| Hi,You can arrive OBSTNAME as RIGHT('00' + sb.BaseName,3) AS OBSTNAMETry it .. so that can avoid the case as well as the sbustring function |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2007-09-26 : 06:03:28
|
"I'm a little confused about why this would result in a query so horribly inefficient for only this table/field"If the most efficient index for a particular query in on, say, Col1 and you do something like:WHERE SomeFunction(Col1)then the Query Optimiser can no longer use the index on that column. Doesn't matter how efficient the function is, the fact that you are no longer using the most efficient index for that query is a killer.Usually anyway ... Kristen |
 |
|
|
Mountain_Nerd
Starting Member
28 Posts |
Posted - 2007-09-26 : 16:46:29
|
| aravindt77... Thanks... that would work if all the values were numeric, but I am trying to do an alphanumeric ordering of street names like 1ST, 23RD, 15TH, 2ND, MAIN, or BROADWAY so that I get, in order:1ST2ND15TH23RDBROADWAYMAINNevertheless, I appreciate your input.Kristen... I think I get what you're saying... definitely something to keep in mind when writing queries. THANKS! |
 |
|
|
|
|
|