July 28, 2004 at 4:21 am
Hi Guys,
There are two DATABASEs (workshop..same name) on two SQL SERVER 1.BOREDEV and 2.SQLDEV.
BOREDEV( SQL Server 2000 )is in a server name BOREDEV(win 2003..same name) and SQLDEV(Sql Server 2000) is on server SQLDEV(win 2003..same name)
This code is run in BOREDEV.workshop.Both the db WORKSHOP on SQLDEV and BOREDEV have the same set of tables.this script basically counts all the rows of all the tables of WORKSHOP in both the databases and gives out the comparison as output.
There are are around 88 Tables which matches the query and the rows in these tables can vary from 0 to 104320935.
This takes typically 30+ minutes to run.Is there any way (tweaking the code ) thorugh which we can get the output quickly.
SET NOCOUNT ON
DECLARE @TableName sysname,
@TableCount INT,
@sql varchar(400)
-- Create the table
CREATE TABLE #tablelist (
TableName varchar(100))
CREATE TABLE #tablecountlist (
TableName varchar(100),
BoreDev int,
Sqldev int)
Insert #tablelist (TableName)
SELECT a.name
FROM sysobjects a
WHERE xtype = 'U'
AND (a.name LIKE 'OBN01%'
or a.name like 'DEV01%'
or a.name like 'calndr%'
or a.name like 'gl04%'
or a.name like 'GL0%'
or a.name like 'hc0%'
or a.name like 'hr0%'
or a.name like 'prod03%'
or a.name like 'kcst01%'
or a.name like 'kdmn01%'
or a.name like 'mtl01%'
or a.name like 'exrate%')
order by a.name
-- Open the cursor
-- Declare cursor for list of indexes to be defragged
DECLARE TableCursor CURSOR FOR
SELECT RTRIM(TableName)
FROM #tablelist
-- Open the cursor
OPEN TableCursor
-- loop through the indexes
FETCH NEXT FROM TableCursor INTO @TableName
WHILE @@FETCH_STATUS = 0 BEGIN
set @sql = 'insert #tablecountlist select ''' + @TableName + ''', (select count(*) from ' + @TableName + '), (select count(*) from sqldev.workshop.dbo.' + @TableName + ')'
exec (@SQL)
FETCH NEXT FROM TableCursor INTO @TableName
END
-- Close and deallocate the cursor
CLOSE TableCursor
DEALLOCATE TableCursor
--select * from #fraglist
-- Delete the temporary table
DROP TABLE #tablelist
select * from #tablecountlist
drop table #tablecountlist
July 28, 2004 at 6:49 am
I have just written a simple piece of code which suffices the purpose specified by you...you can enhance it if u need it to do more ...It takes less than a minute for me to execute on my DB..which is not very huge (just a few tables with a couple of million rows and around 400+ tables). Pls try it on yours !!
Create Table #t
(rowid int identity(1,1),
DBName varchar(150),
TblName varchar(50),
Rowcnt int
)
Insert into #t (DBName, TblName)
select Host_Name() + '.' + db_name(), name from sysobjects where type = 'u'
Declare @cnt int,
@i int,
@sql nvarchar(200),
@tblname sysname
Select @cnt = @@rowcount
Select @i = 1
While @i <= @cnt
Begin
Select @tblname = TblName From #t where rowid = @i
Set @sql = 'Update #t Set Rowcnt = A.cnt From (Select Count(*) AS cnt from ' + @tblname + ') A Where tblname = ' + ''''+@tblname+''''
Execute (@sql)
-- select @sql
Set @i = @i + 1
End
Select * from #t
Drop table #t
I prefer to use the While Loop instead of a Cursor coz its usually faster than the Cursor.
Hope it helps!
Cheers,
Arvind
July 28, 2004 at 7:50 am
You don't need to use count(*) to achieve this the number of rows in a table is stored in sysindexes.
e.g
SELECT rows
FROM DBName..sysindexes
WHERE OBJECT_ID('DBName..'+@tablename)= id and (indid = 0 or indid = 1)
This should be faster.
Dave
July 28, 2004 at 11:10 pm
Awesome !! It worked.
Earlier It used to take 35 minutes.
Arvind - Your suggestion brought it down to 25 minutes !!!
David - Your suggestion brought it down to whopping 30 Seconds !!!
Thanks a million .I really appreciate that.
Debjit
July 29, 2004 at 12:39 am
Thats really cool Debjit.
Dave - Thx for the excellent suggestion...Never thot abt using the rows from sysindexes...
Out of curiosity...i am sure this will work fine for tables with clustered index but wud the count be rebuilt or updated in case of broken indexes or chaining issues with tables having only non clustered indexes.?
Cheers,
Arvind
July 29, 2004 at 11:41 am
Arvind
I had the same queries when i started using this method and have never yet got an incorrect number of rows whether it has been a clustered or non-clustered index or even no index.
But if you do find any issues let me know.
Dave
July 30, 2004 at 6:25 am
Guys,
1. if there is no key defined in a table , in that case will sysindexes contain the rowcount.
2.One more thing how to convert a row from Null to 0,if that row has a formula.ROWCNT column has a formula and i am getting NUll , no matter how much i try it,if the field is 0.
If i run the query in the particular server it returns 0 but when run from a different server it is coming as NULL.
I have tried CAST,CONVERT,ISNULL,SET_ANSI_NULLS (ON/OFF) but nothing worked.
Debjit
July 30, 2004 at 6:47 am
1. SysIndexes system table will contain the number of rows for each table in the db. Existence of indexes is not a factor.
rows will be populated against the row with indid = 0 for a heap (table without indexes)
rows will be populated against the row with indid = 1 for a Clustered Index. Thats why the "(indid = 0 or indid = 1)" in the where clause.
Always indid = 0 contains the value for a Heap and indid = 1 refers to the Clustered Index and from there on indid 2 - 250 refer to Non Clustered Indexes. indid = 255 refers to columns with text, ntext, image data types etc.
2. I am sure you must have tried ISNULL() but in case you havent you better try that. In case you have tried that...need some more info on the data type and the query if possible.
Cheers!
Arvind
July 30, 2004 at 6:50 am
Sorry a Heap is a table without a CLUSTERED Index. missed that important detail.
Cheers!
Arvind
August 1, 2004 at 6:25 am
Hi Arvind,
here is the script..
It is run on boredev.workshop
SET NOCOUNT ON
DECLARE @TableName sysname,
@TableCount INT,
@sql varchar(400),
@cnt INT,
@i int
-- Create the table
CREATE TABLE #tablelist (
rowid int identity(1,1),
TableName varchar(100))
CREATE TABLE #tablecountlist (
TableName varchar(100),
BoreDev int,
Sqldev int)
Insert #tablelist (TableName)
SELECT a.name
FROM sysobjects a
WHERE xtype = 'U'
AND (a.name LIKE 'OBN01%'
or a.name like 'DEV01%'
or a.name like 'calndr%'
or a.name like 'gl04%'
or a.name like 'GL0%'
or a.name like 'hc0%'
or a.name like 'hr0%'
or a.name like 'prod03%'
or a.name like 'kcst01%'
or a.name like 'kdmn01%'
or a.name like 'mtl01%'
or a.name like 'exrate%')
order by a.name
Select @cnt = @@rowcount
Select @i = 1
While @i <= @cnt
Begin
Select @TableName = TblName From #tablelist where rowid = @i
set @sql = 'insert #tablecountlist select ''' + @TableName + ''',
(SELECT rows FROM workshop..sysindexes
WHERE OBJECT_ID('+ ''''+ ' workshop..' + @TableName + ''''+ ')= id'+ ' and '
+ '(indid = 0 or indid = 1)'+ ')
, (SELECT rows FROM sqldev.workshop.dbo.sysindexes
WHERE OBJECT_ID('+ ''''+ ' workshop..' + @TableName + ''''+ ')= id'+ ' and '
+ '(indid = 0 or indid = 1)' + ')'
exec (@SQL)
Set @i = @i + 1
End
DROP TABLE #tablelist
select * from #tablecountlist
drop table #tablecountlist
-> Infact if run this query in SQLDEV it gives(ex. of one table)
SELECT rows FROM sqldev.workshop.dbo.sysindexes WHERE OBJECT_ID('workshop..HC01Alpha')= id and (indid = 0 or indid = 1)
output :
rows
---
0
If i run the same query from BOREDEV ,it gives me blank space
rows
----
ANd when i run it as a part of the script it gives me NULL.
I tried ISNULL it didnt work.
Thanks,
Deb
August 2, 2004 at 2:26 am
Hi Deb,
I was getting NULL for some of the tables when i ran the script on my DB. But when i tried this
ISNULL( (SELECT rows FROM sqldev.workshop.dbo.sysindexes WHERE OBJECT_ID('+ ''''+ ' workshop..' + @TableName + ''''+ ')= id'+ ' and ' + '(indid = 0 or indid = 1)' + ') , 0) '
ISNULL for the whole select statement itself...Then i got 0 instead of NULL...Not sure if you tried this...Lemme know if this helps.
Cheers!
Arvind
August 3, 2004 at 1:33 am
even i tried of doing that !!!.but there was a confusion in the quotes sign so i didnt tried it finally
Thanks anyways...
Deb
Viewing 12 posts - 1 through 12 (of 12 total)
You must be logged in to reply to this topic. Login to reply