SELECT
o1.name AS FK_table,
c1.name AS FK_column,
fk.name AS FK_name,
o2.name AS PK_table,
c2.name AS PK_column,
pk.name AS PK_name,
fk.delete_referential_action_desc AS Delete_Action,
fk.update_referential_action_desc AS Update_Action
FROM sys.objects o1
INNER JOIN sys.foreign_keys fk
ON o1.object_id = fk.parent_object_id
INNER JOIN sys.foreign_key_columns fkc
ON fk.object_id = fkc.constraint_object_id
INNER JOIN sys.columns c1
ON fkc.parent_object_id = c1.object_id
AND fkc.parent_column_id = c1.column_id
INNER JOIN sys.columns c2
ON fkc.referenced_object_id = c2.object_id
AND fkc.referenced_column_id = c2.column_id
INNER JOIN sys.objects o2
ON fk.referenced_object_id = o2.object_id
INNER JOIN sys.key_constraints pk
ON fk.referenced_object_id = pk.parent_object_id
AND fk.key_index_id = pk.unique_index_id
ORDER BY o1.name, o2.name, fkc.constraint_column_id
This blog is created to add all the information and experiences that I have learnt while working on MS sql server as a DBA. The blog is also updated frequently with the real world problem that I encounter hands on at work and the resolutions to resolve them. I hope this blog will be of some use to you and you will revisit. Thank you for stopping by and you are welcome to leave comments.
Wednesday, January 14, 2015
Tuesday, January 13, 2015
Diskspace analysis, database growth (yearly)
I am using the following query to forecast the yearly database growth
select cast(MAX(Space_Used_in_MB)as float) as max_size , min(Space_Used_in_MB) AS MIN_SIZE ,
cast((MAX(Space_Used_in_MB) - MIN(Space_Used_in_MB)) as decimal(18,2))/ MIN(Space_Used_in_MB) * 100 as [yearly percent growth] ,
Database_Name from SQLMonitor..SQLAdmin_Monitor_db_file_info
where FILE_ID = 1
and Time_collected >='01/13/2014'
group by Database_Name
order by database_name
--SQLMonitor is a user database
--SQLAdmin_Monitor_db_file_info is a user table where a job ( code here) logs the database file sixe in every four hours
-- if the time frame you want to measure is two years change the time_collected to '01/13/2013' and change the yearly percent growth calculation as follows
( cast((MAX(Space_Used_in_MB) - MIN(Space_Used_in_MB)) as decimal(18,2))/ MIN(Space_Used_in_MB) * 100 )/2
Linear: Current disk space + (growth * No of periods)
Compound: Current disk space * (1 + Growth %) ^ No of periods
Geometric: Current growth + [initial increment * {1-Incrementgrowth rate^ (No of period+1)}]/ (1 – growth rate)
To illustrate the fact, let us take one example. Say for, you have a database and it is of 100 GB. If it grows at 10% per year, then after 2 years, it will be 100 + (10 * 2) = 120 GB (linear growth).
If it is so that the database grows at 5% rate/month for 2 years, then it will be
100 * (1 + 0.05) ^ 24 = 322.5 GB (compound growth).
Take another case. Say for you have already a database of 100GB. Now the growth rate is so that it starts at 10 GB/month and the increment itself increments at 5%/month, then in 24 months, it will be 100 + {(10 * (1- (1.05 ^ (24 + 1))) / (1-1.05)} = 100 + 477 = 577 GB (geometric growth).
select cast(MAX(Space_Used_in_MB)as float) as max_size , min(Space_Used_in_MB) AS MIN_SIZE ,
cast((MAX(Space_Used_in_MB) - MIN(Space_Used_in_MB)) as decimal(18,2))/ MIN(Space_Used_in_MB) * 100 as [yearly percent growth] ,
Database_Name from SQLMonitor..SQLAdmin_Monitor_db_file_info
where FILE_ID = 1
and Time_collected >='01/13/2014'
group by Database_Name
order by database_name
--SQLMonitor is a user database
--SQLAdmin_Monitor_db_file_info is a user table where a job ( code here) logs the database file sixe in every four hours
-- if the time frame you want to measure is two years change the time_collected to '01/13/2013' and change the yearly percent growth calculation as follows
( cast((MAX(Space_Used_in_MB) - MIN(Space_Used_in_MB)) as decimal(18,2))/ MIN(Space_Used_in_MB) * 100 )/2
Growth of database ( http://www.sqlservercentral.com/articles/Administration/analyzingdiskcapacityforsqlserver/2467/)
Database growth can be of three types:- linear growth (grows at a constant amount over time)
- compound growth (grows at a constant rate for a specific period of time)
- geometric growth (grows periodic by some increment, which is in turn growing at a constant rate)
Linear: Current disk space + (growth * No of periods)
Compound: Current disk space * (1 + Growth %) ^ No of periods
Geometric: Current growth + [initial increment * {1-Incrementgrowth rate^ (No of period+1)}]/ (1 – growth rate)
To illustrate the fact, let us take one example. Say for, you have a database and it is of 100 GB. If it grows at 10% per year, then after 2 years, it will be 100 + (10 * 2) = 120 GB (linear growth).
If it is so that the database grows at 5% rate/month for 2 years, then it will be
100 * (1 + 0.05) ^ 24 = 322.5 GB (compound growth).
Take another case. Say for you have already a database of 100GB. Now the growth rate is so that it starts at 10 GB/month and the increment itself increments at 5%/month, then in 24 months, it will be 100 + {(10 * (1- (1.05 ^ (24 + 1))) / (1-1.05)} = 100 + 477 = 577 GB (geometric growth).
Perfmon helpful couters
Buffer cache hit ratio :
It is the percentage of data server had in the cache and did not have to read it from the disk.
Buffer cache hit ratio should be more than 90% for a SQL Server
SELECT (a.cntr_value * 1.0 / b.cntr_value) * 100.0 as BufferCacheHitRatio
FROM sys.dm_os_performance_counters a
JOIN (SELECT cntr_value,OBJECT_NAME
FROM sys.dm_os_performance_counters
WHERE counter_name = 'Buffer cache hit ratio base'
AND OBJECT_NAME = 'SQLServer:Buffer Manager') b ON a.OBJECT_NAME = b.OBJECT_NAME
WHERE a.counter_name = 'Buffer cache hit ratio'
AND a.OBJECT_NAME = 'SQLServer:Buffer Manager'
Page Life Expectancy (PLE) :
It is the number of seconds the data will stay in the cache. The ideal value is 300 if less than 300 or between 300-400 the sever will require more memory.
SELECT *,cntr_value as [PLE in secs],cntr_value / 60 as [PLE in mins],
cntr_value / 3600 as [PLE in hours],
cntr_value / 86400 as [PLE in days]
FROM sys.dm_os_performance_counters
WHERE counter_name = 'Page life expectancy'
AND OBJECT_NAME = 'SQLServer:Buffer Manager'
It is the percentage of data server had in the cache and did not have to read it from the disk.
Buffer cache hit ratio should be more than 90% for a SQL Server
SELECT (a.cntr_value * 1.0 / b.cntr_value) * 100.0 as BufferCacheHitRatio
FROM sys.dm_os_performance_counters a
JOIN (SELECT cntr_value,OBJECT_NAME
FROM sys.dm_os_performance_counters
WHERE counter_name = 'Buffer cache hit ratio base'
AND OBJECT_NAME = 'SQLServer:Buffer Manager') b ON a.OBJECT_NAME = b.OBJECT_NAME
WHERE a.counter_name = 'Buffer cache hit ratio'
AND a.OBJECT_NAME = 'SQLServer:Buffer Manager'
Page Life Expectancy (PLE) :
It is the number of seconds the data will stay in the cache. The ideal value is 300 if less than 300 or between 300-400 the sever will require more memory.
SELECT *,cntr_value as [PLE in secs],cntr_value / 60 as [PLE in mins],
cntr_value / 3600 as [PLE in hours],
cntr_value / 86400 as [PLE in days]
FROM sys.dm_os_performance_counters
WHERE counter_name = 'Page life expectancy'
AND OBJECT_NAME = 'SQLServer:Buffer Manager'
Labels:
Administration,
cache,
memory,
memory management,
perfmon,
performance,
PLE
Tuesday, January 6, 2015
Reasons for database to go to SUSPECT mode
Possibility 1 : Someone deleted or misplaced a log/data file when SQL server was offline so the database could not start as it is missing a file.
Solution : Put the missing file back on the location. SQL error log will give the exact location of the missing file.
Possibility 2 : SQL server could not access to put an exclusive lock on the data/log file while the database was starting up . This could be caused when the data SQL server is shared with some other tool ( e.g. antivirus)
Solution: Find the file handler that placed an exclusive lock on the data/log file and kill it. Then run the following query.
RESTORE DATABASE WITH RECOVERY
Possibility 3 : Due to a corrupted transaction. This could likely be that the SQL server went down in the middle of the transaction and while coming back it could not complete ( COMMIT/ROLLBACK) the transaction.
Solution: Switch to emergency mode and run the dbcc checkdb command
Possibility 4: Some OS/hardware failure
Solution : Put the missing file back on the location. SQL error log will give the exact location of the missing file.
Possibility 2 : SQL server could not access to put an exclusive lock on the data/log file while the database was starting up . This could be caused when the data SQL server is shared with some other tool ( e.g. antivirus)
Solution: Find the file handler that placed an exclusive lock on the data/log file and kill it. Then run the following query.
RESTORE DATABASE WITH RECOVERY
Possibility 3 : Due to a corrupted transaction. This could likely be that the SQL server went down in the middle of the transaction and while coming back it could not complete ( COMMIT/ROLLBACK) the transaction.
Solution: Switch to emergency mode and run the dbcc checkdb command
Possibility 4: Some OS/hardware failure
Friday, January 2, 2015
Batch Update : using TOP n
---do not use set rowcount.
--Use top n
WHILE (1=1)
BEGIN
BEGIN TRANSACTION
UPDATE r
SET col1= col2
from Table1 r
where r.col3 in (select top 10000 col3 from Table1 where col1 is null)
-- Update 10000 nonupdated rows
IF @@ROWCOUNT = 0
BEGIN
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
END
--Use top n
WHILE (1=1)
BEGIN
BEGIN TRANSACTION
UPDATE r
SET col1= col2
from Table1 r
where r.col3 in (select top 10000 col3 from Table1 where col1 is null)
-- Update 10000 nonupdated rows
IF @@ROWCOUNT = 0
BEGIN
COMMIT TRANSACTION
BREAK
END
COMMIT TRANSACTION
END
Labels:
batch update,
cool t-sqls,
query,
select top,
top n,
update
Monday, October 20, 2014
suspect mode: database
---once the database goes to suspect mode
--follow the steps to recover the database
--1. reset the database from suspect mode
--sp_resetstatus turns off the suspect flag on a database.
--This procedure updates the mode and status columns of the named database in sys.databases.
--Also note that only logins having sysadmin priveleges can perform this :
use master
GO
exec sp_resetstatus 'db1';
--2.set the database to emergency mode
--Once the database is set to EMERGENCY mode it becomes a READ_ONLY copy
--only members of sysadmin fixed server roles have privileges to access it.
--The basic purpose for this is to facilitate troubleshooting
alter database db1 set emergency;
--3.run the consistency test
dbcc checkdb(db1)
--4. Roll the databse to single user mode
use master
GO
ALTER DATABASE db1 SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
--5. this query will attempt to repir all the reported loss. This query can cause some data loss
dbcc checkdb('db1',REPAIR_ALLOW_DATA_LOSS)
--6.finally bring the database ONLINE and set to multiuser mode
ALTER DATABASE db1 SET MULTI_USER
WITH ROLLBACK IMMEDIATE
--follow the steps to recover the database
--1. reset the database from suspect mode
--sp_resetstatus turns off the suspect flag on a database.
--This procedure updates the mode and status columns of the named database in sys.databases.
--Also note that only logins having sysadmin priveleges can perform this :
use master
GO
exec sp_resetstatus 'db1';
--2.set the database to emergency mode
--Once the database is set to EMERGENCY mode it becomes a READ_ONLY copy
--only members of sysadmin fixed server roles have privileges to access it.
--The basic purpose for this is to facilitate troubleshooting
alter database db1 set emergency;
--3.run the consistency test
dbcc checkdb(db1)
--4. Roll the databse to single user mode
use master
GO
ALTER DATABASE db1 SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
--5. this query will attempt to repir all the reported loss. This query can cause some data loss
dbcc checkdb('db1',REPAIR_ALLOW_DATA_LOSS)
--6.finally bring the database ONLINE and set to multiuser mode
ALTER DATABASE db1 SET MULTI_USER
WITH ROLLBACK IMMEDIATE
Thursday, October 16, 2014
Stored procedure with an OUTPUT parameter
CREATE procName1 (@intClientId int, @account varchar(50), @intCount int OUTPUT)
AS
SELECT @intCount = COUNT (*) FROM Clients where clientId = @intClientId
SELECT @intCount
GO
--procedure call
Declare @out int
EXECUTE procName1 999, 'ABCSDRF',@out OUTPUT
SELECT @out
AS
SELECT @intCount = COUNT (*) FROM Clients where clientId = @intClientId
SELECT @intCount
GO
--procedure call
Declare @out int
EXECUTE procName1 999, 'ABCSDRF',@out OUTPUT
SELECT @out
Subscribe to:
Posts (Atom)