| Author |
Topic |
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 04:36:53
|
| A friend needs to produce a coding standards document.Not so much naming standards but methods of coding.Like avoiding cursors, not in, not exists, tables without unique indexes (that'll be fun - none there at the moment :( ).I'm sure I've been involved in a discussion about this and seen some quite good documents - of course I can't find any now.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy. |
|
|
Wanderer
Master Smack Fu Yak Hacker
1168 Posts |
Posted - 2002-10-17 : 05:45:16
|
| Got to be honest, I'd love to see this, esp. if it carries reasonings behind the points, and not just - "don't do that, do this"****I've seen some mails on another group saying that one should rather use the "table data type" rather than temp tables (SQL 2K from what I can see). Apparently they are more efficient.**** |
 |
|
|
smccreadie
Aged Yak Warrior
505 Posts |
Posted - 2002-10-17 : 05:51:44
|
| I can't find a document that explicitly states these. There is a tool which we're considering (http://www.fmsinc.com/Products/sqlanalyzer/Guide.htm) that appears to identify bad coding practices. |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 06:24:50
|
| Ok lets try building a list - I'll edit this with any additions/removalsMove of these apply to large sets and can be ignored if the operation applies to a small amount of data.Also it may be that in some situations the best solution would be to violate these suggestions.Don't use CursorsEvery table should have a unique indexEvery identity column should have a unique indexAvoid "not in", "<>"Avoid "in"Avoid correlated subqueriesUtilise indexes i.e. make sure you include the first field of the index in the join.Take into account the effect (locking, resources) of other processes running on the server.Put a "set nocount on" at the top of every SP.Limit cross database processes - take into account the backup/restore process (especially for updates) and permissions.Limit cross server processes - these should be via a single channel and the system should allow for long term failure of the link / database restores.if possible, use table variables or derived tables instead of temp tables - but be wary of overcomplicating queries.if using temp tables, determine if creating indexes on them would help performanceInclude a test call in comments at the top of every stored procedure.Any import/export of data should be coded as an asynchronous call so that the method could be changed if necessary without impacting any processing.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy.Edited by - nr on 10/17/2002 08:17:40 |
 |
|
|
Page47
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2002-10-17 : 06:55:33
|
| What's wrong with "<>" and correlated subqueries?How bout something like "All procs with subtree cost > 1 must be reviewed by entire db team..." I always thought that was a good way to force people to look at the execution plan before moving on to the next proc.Jay White{0} |
 |
|
|
Andraax
Aged Yak Warrior
790 Posts |
Posted - 2002-10-17 : 06:59:44
|
| - if possible, use table variables or derived tables instead of temp tables- if using temp tables, determine if creating indexes on them would help performance |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 08:14:01
|
| <> won't use an index.Correlated subqueries tend to be slow - especially when nested.Just something to watch out for==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
Page47
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2002-10-17 : 08:33:58
|
quote: <> won't use an index.
What's the alternative?Gimme everybody from pubs.dbo.authors where au_lname <> 'white'Jay White{0} |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 09:14:23
|
| since you asked (not serious).assuming au_lname is the PK - can't be bothered to look.select a.*from pubs.dbo.authors a left outer join pubs.dbo.authors bon a.au_lname = b.au_lname and b.au_lname = 'white' where b.au_lname is nullThe point is that a <> will table scan so if you can use another index you should or reduce the size of the result set before using it.In your example you want to return almost the whole table (probably) so a table scan is a good idea.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
Page47
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2002-10-17 : 09:46:20
|
nr, I don't mean to derail your thread here, but I don't get the '<>' thing.drop table #testgocreate table #test ( rownum int identity(1,1) not null primary key, n int not null )create nonclustered index idx_n on #test(n) insert #test (n)select n%10from numbers --tally table with ints from 1 to 10000go Looking at the plan of ...select *from #testwhere n <> 1 I am seeing a 0.0268 cost and a index seek of idx_n ... now looking at ...select *from #test a left join #test b on a.rownum = b.rownum and b.n = 1where b.rownum is null ...It is presenting a 0.107, with a scan on the pk, a seek on idx_n. I don't see how the latter is better? What am I missing?Jay White{0} |
 |
|
|
Arnold Fribble
Yak-finder General
1961 Posts |
Posted - 2002-10-17 : 10:03:10
|
The join version should be selecting a.*You didn't mention that the join version gives completely the wrong row count estimate.Shouldn't you be testing this too, just for completeness?select *from #testwhere rownum not in (select rownum from #test where n = 1) Edited by - Arnold Fribble on 10/17/2002 10:07:13 |
 |
|
|
Page47
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2002-10-17 : 10:08:09
|
| The a.* doesn't effect the plan, but yeah, I noticed that after the post ...The not in version has roughly the same plan as the left join, except without the filter on b.rownum is null.Jay White{0} |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 10:12:21
|
| I was just showing how you could avoid a <> - that's why I said it wasn't serious.You are returning 99999 of 100000 rows so of course a scan is going to be most efficient. For this it is better to not use an index.In fact I'm a bit surprised it does an index seek seeing as it should know that it has to return all rows but one - but then a <> is not easy to optimise.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
Page47
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2002-10-17 : 10:15:48
|
| No, the #test is n%10, so it is returning 9999 records.... and it does use the index (idx_n) ... and its a seek at that? It's the exact same query plan and cost as an n=1 ... this is what I am trying to say ...Jay White{0} |
 |
|
|
royv
Constraint Violating Yak Guru
455 Posts |
Posted - 2002-10-17 : 10:20:22
|
| I would say that every table should have a unique clustered index. Some problems have arisen that can be fixed when readding the clustered index, like freeing up data pages.*************************Someone done told you wrong! |
 |
|
|
Arnold Fribble
Yak-finder General
1961 Posts |
Posted - 2002-10-17 : 10:26:17
|
So something more like this?drop table #testgocreate table #test ( rownum int identity(1,1) not null primary key, n int not null )create nonclustered index idx_n on #test(n) insert #test (n)select case when n % 2702 = 0 then n%10 else 1 endfrom numbers --tally table with ints from 1 to 10000go what the hell is a Merge Interval, anyway?Edited by - Arnold Fribble on 10/17/2002 10:27:46 |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 10:38:02
|
quote: No, the #test is n%10, so it is returning 9999 records.... and it does use the index (idx_n) ... and its a seek at that? It's the exact same query plan and cost as an n=1 ... this is what I am trying to say ...Jay White{0}
OK doesn't really matter how many recs are in the table.Using the index would be good for the = but is it good for <>?Why would you traverse index pages to get get to all recs bar one when you can just use the page chain - in this case I suspect a table scan would have been better.<> does not restrict rows very much usually and doesn't allow useful index usage usually - that's why you should be cautious about it, same as "not in".==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 10:52:19
|
| (v7 sp2)set nocount oncreate table #a (i int, j char(2000))create table #b (i int, j char(2000))declare @i intselect @i = 10000while @i > 0beginselect @i = @i -1insert #a select convert(int,rand() * 1000), ''endcreate index ix on #a (i)create clustered index ix1 on #a (i)insert #bselect *from #awhere i <> 50With the clustered index it does a range scan of the clustered index. With the same index as non-clustered it does a table scan.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy.Edited by - nr on 10/17/2002 10:52:49 |
 |
|
|
Arnold Fribble
Yak-finder General
1961 Posts |
Posted - 2002-10-17 : 11:10:47
|
quote: With the clustered index it does a range scan of the clustered index. With the same index as non-clustered it does a table scan.
Er, yes. I'm obviously missing something here, because that's exactly what I'd expect to happen. |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2002-10-17 : 11:19:22
|
| Yep - the point is a <> won't make effective use of an index.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
VyasKN
SQL Server MVP & SQLTeam MVY
313 Posts |
Posted - 2002-10-17 : 12:02:40
|
I do have a similar article at: http://vyaskn.tripod.com/coding_conventions.htmBeen a while since I wrote it. Some of the points might be out dated or need updating.quote: A friend needs to produce a coding standards document.Not so much naming standards but methods of coding.Like avoiding cursors, not in, not exists, tables without unique indexes (that'll be fun - none there at the moment :( ).I'm sure I've been involved in a discussion about this and seen some quite good documents - of course I can't find any now.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy.
--HTH,Vyashttp://vyaskn.tripod.com |
 |
|
|
Next Page
|