I use SQL Server 2008 R2, I need to rebuild the index for every table in a database
Using this script, I receive an error
USE myDb
GO
EXEC sp_MSForEachTable 'ALTER INDEX ALL ON ? REBUILD'
Error:
ALTER INDEX failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are
correct for use with indexed views and/or indexes on computed columns
and/or filtered indexes and/or query notifications and/or XML data
type methods and/or spatial index operations.
Any idea how to fix it? thanks
SQL Fool (Michelle Ufford) has a great script to do this for you - all done and well tested by many users.
It's a great piece of work - it allows you to define fragmentation levels for which you
do nothing
reorganize an index
rebuild an index
Don't reinvent the wheel - just go see and use the script!
A simple approch I decide to use for my questions. Code from: http://blog.sqlauthority.com/2009/01/30/sql-server-2008-2005-rebuild-every-index-of-all-tables-of-database-rebuild-index-with-fillfactor/
-- Rebuild eve Index for every Table in the Database.
-- Resource: http://blog.sqlauthority.com/2009/01/30/sql-server-2008-2005-rebuild-every-index-of-all-tables-of-database-rebuild-index-with-fillfactor/
USE [YourDbName]
GO
-- Show Fragmentation sample on YourTable Index.
select avg_fragmentation_in_percent, avg_fragment_size_in_pages, fragment_count, avg_page_space_used_in_percent
from sys.dm_db_index_physical_stats (DB_ID(), object_id('[dbo].[YourTableName]'), NULL, NULL, 'DETAILED')
-- Cursor going over each table and rebuilding every index of database.
DECLARE #TableName VARCHAR(255)
DECLARE #sql NVARCHAR(500)
DECLARE #fillfactor INT
SET #fillfactor = 80
DECLARE TableCursor CURSOR FOR
SELECT OBJECT_SCHEMA_NAME([object_id])+'.'+name AS TableName
FROM sys.tables
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'ALTER INDEX ALL ON ' + #TableName + ' REBUILD WITH (FILLFACTOR = ' + CONVERT(VARCHAR(3),#fillfactor) + ')'
EXEC (#sql)
FETCH NEXT FROM TableCursor INTO #TableName
END
CLOSE TableCursor
DEALLOCATE TableCursor
GO
Related
We have production database above 100Gig. I want to duplicate this database and give it to every developer to test its code, but the size is too large. Is there anyway I can backup just top 1000 rows with FK's and restore it to new DB? Or duplicate the DB first and delete all records from all tables, but keep 1000 rows with FK's or any other way to keep size below 5Gig.
I did search, but none of solutions were for tables having foreign keys.
Thanks,
Basheer
This the IDEA:
First:
Create new database:
Second:
Select small records only like:
select top 500 from allYourTables
then insert to each every table to your new Database Created.
Third:
Dump the new database and give to its every developer
Hope it helps:
Assuming that you have a new db_to_dev Database name and you are working to your current database:
This procedure will insert all the data from your working database, making sure that you had already a database created. db_to_dev:
Using Information_Schema you can select all your tables:
CREATE PROCEDURE PROC_TRANSFER_DATA #NUM_OF_RECORDS nvarchar(255) as
BEGIN
SET NOCOUNT ON;
DECLARE #message varchar(80), #tablename nvarchar(50);
Declare #sqlstmt nvarchar(255);
PRINT '-------- List of tables --------';
DECLARE Schema_cursor CURSOR FOR
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
OPEN Schema_cursor
FETCH NEXT FROM Schema_cursor INTO #tablename
IF ##FETCH_STATUS <> 0
PRINT ' <<None>>'
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #message = ' ' + #tablename
set #sqlstmt = 'select top ' + #NUM_OF_RECORDS + ' * into [db_to_dev].[dbo].['+ #tablename +'] from ' + #tablename;
EXEC sp_executesql #sqlstmt
PRINT #message
FETCH NEXT FROM Schema_cursor INTO #tablename
END
CLOSE Schema_cursor
DEALLOCATE Schema_cursor
END
To use:
With an option parameter:
EXEC PROC_TRANSFER_DATA '500'
Parameter value is depend on you if how many records you want to transfer into your new database db_to_dev.
This Stored Proc is tested.
Good luck
There are a number of projects on github which seek to do exactly that: make a subset that preserves referential integrity. Here is one such project:
https://github.com/18F/rdbms-subsetter
We have a few test databases that we are throwing test indexes into and the log file gets bloated real quickly due to us dropping the contents of the table and repopulating it.
I have found, thanks to Stack Overflow, a few scripts and put them together to do what I need.
Here is the script:
USE SSSIndexes
GO
ALTER DATABASE SSSIndexes SET RECOVERY SIMPLE WITH NO_WAIT
GO
DBCC SHRINKFILE(N'SSSIndexes_Log', 1) <-- my issue is here
GO
The problem is the log file name. Is there a way to get the log file name without having to look it up manually and include it in the script to where this part is automated?
Btw, we never intend on restore this database. These are temporary indexes.
Thanks!
USE SSSIndexes
GO
ALTER DATABASE SSSIndexes SET RECOVERY SIMPLE WITH NO_WAIT
GO
DECLARE #Name NVARCHAR(50)
DECLARE cur CURSOR FOR
SELECT [name]
FROM [sys].[database_files]
where [type] = 1
OPEN cur
FETCH NEXT FROM cur INTO #Name
WHILE ##FETCH_STATUS = 0
BEGIN
DBCC SHRINKFILE(#Name, 1)
FETCH NEXT FROM cur INTO #Name
END
CLOSE cur
DEALLOCATE cur
You can use this to generate script for log file truncating of all databases on a specific server. To stick to specific databases use a filter.
SELECT
' USE [' + name + ']; GO
-- Truncate the log by changing the database recovery model to SIMPLE.
ALTER DATABASE [' + name + '] SET RECOVERY SIMPLE;
GO
-- Shrink the truncated log file to 1 MB.
DECLARE #logname varchar(128);
SELECT TOP 1 #logname=[name] FROM [' + name + '].[sys].[database_files] WHERE [type] = 1;
DBCC SHRINKFILE (#logname, 1);
GO
-- Reset the database recovery model.
ALTER DATABASE [' + name + '] SET RECOVERY FULL;
GO
' AS qry FROM master.dbo.sysdatabases
WHERE dbid > 6
WARNING!!!: YOU SHOULD ONLY DO THIS ON TEST DB SERVERS. Production DBs typically WANT to have FULL recovery mode. Test DBs you usually don't care.
Expanding on Abdul's answer (I had trouble getting it to show in new lines) and Dis' answers this finds the first db that has recovery FULL, sets it to simple and shrinks it... just keep clicking execute until it returns null
declare #dbname nvarchar(50)
declare #logfilename nvarchar(100)
select top(1) #dbname = name from sys.databases where recovery_model_desc <> 'SIMPLE' AND name <> 'tempdb'
declare #shrinkdb nvarchar(500)
set #shrinkdb = 'USE master
ALTER DATABASE [' + #dbname + '] SET RECOVERY SIMPLE
'
select #shrinkdb
execute sp_executesql #shrinkdb
set #shrinkdb = 'USE [' + #dbname + ']
DECLARE #Name NVARCHAR(50)
DECLARE cur CURSOR FOR
SELECT [name]
FROM [sys].[database_files]
where [type] = 1
OPEN cur
FETCH NEXT FROM cur INTO #Name
WHILE ##FETCH_STATUS = 0
BEGIN
DBCC SHRINKFILE(#Name, 1)
FETCH NEXT FROM cur INTO #Name
END
CLOSE cur
DEALLOCATE cur
'
select #shrinkdb
execute sp_executesql #shrinkdb
I am doing the index rebuilding on database.
I need to verify if it is done or not.
Can somebody please guide me.
I am using SQL Server 2008 R2
If you are looking for details on all indexes and tables in your database you can use.
SELECT OBJECT_NAME(object_id),*
FROM sys.dm_db_index_physical_stats(DB_ID(),NULL,NULL,NULL,'SAMPLED')
It just occurred to me that you might also be asking how to know the progress of the reindexing. For this you can use
SELECT percent_complete
from sys.dm_exec_requests
where session_id= <spid of interest>
A key thing would be to run the "Index Physical Statistics" report and "Disk Usage by Top Tables" reports before and after you rebuild the indexes.
On the "Index Physical Statistics" report, you can see how fragmented each index is.
To see these reports...
* Right Click on database in Sql Server Management Studio
* Mouse over "Reports", then "Standard Reports", then select the report you want.
For a script you can set up to identify fragmented indexes and rebuild them (and for more info), check this out:
http://www.foliotek.com/devblog/sql-server-optimization-with-index-rebuilding/
If you have successfully re-indexed your tables, then the index fragmentation will be zero (or close to if you have hot tables). You can use this script to check the fragmentation level
DECLARE
#IndexID int,
#TableID int,
#IndexName varchar(256)
--Enter index name here
SELECT #IndexName = '<index name>'
--Enter table name here
SET #TableID = OBJECT_ID('<table name>')
SELECT #IndexID = IndID
FROM sysindexes
WHERE
id = #TableID
AND name = #IndexName
DBCC SHOWCONTIG (#id, #IndexID)
What you are looking for in the output is the property called Scan Density. This should be close to 100%. If not, then your re-indexing is not complete/successful
If you have lots of tables/indices, this can get tedious, so short-circuit it by auto-generating the script like this:
SELECT 'DBCC SHOWCONTIG ' +
'('
+ CONVERT(varchar(32), si.id) + ','
+ CONVERT(varchar(32), si.indid) +
')--' + so.name
FROM sysobjects so
INNER JOIN sysindexes si
ON (so.id = si.id)
WHERE (
so.type = 'U' AND
si.indid < 2 AND
si.id = object_id(so.name)
)
You can try this procedure. It will rebuild the index of all the tables in the database and print the result as it progresses to the message pane of your Management Studio:
CREATE PROCEDURE [dbo].[ReIndexDatabase]
AS
DECLARE #MyTable VARCHAR(255)
DECLARE myCursor
CURSOR FOR
SELECT table_name
FROM information_schema.tables
WHERE table_type = 'base table'
OPEN myCursor
FETCH NEXT
FROM myCursor INTO #MyTable
WHILE ##FETCH_STATUS = 0 BEGIN
PRINT 'Reindexing Table: ' + #MyTable
EXEC('ALTER INDEX ALL ON '+#MyTable+'
REBUILD WITH (FILLFACTOR = 80, SORT_IN_TEMPDB = OFF,
STATISTICS_NORECOMPUTE = ON)');
FETCH NEXT FROM myCursor INTO #MyTable
END
CLOSE myCursor
DEALLOCATE myCursor
EXEC sp_updatestats
You can see this link for more on re-indexing or this link.
Note the information at the top of the page.
I'd like to clear a database's schema on my SqlServer instance. What tsql should I use?
By schema I mean tables, constraints, etc. I want the result to be similar to if I created a new database, however I don't want to actually drop and create the database.
Why:
For those curious, I need to empty the schema without dropping because of the way the database is being isolated for unit tests. Before running my tests a snapshot of the database is saved. After each test runs, this snapshot is restored. I can only ensure consistent state across unit tests if I keep my db operations within the scope of the database. Dropping/Create the database is outside of the db's scope (its in the master's scope).
In this case, I need to assert that an expected thing happens when the schema is empty. Emptying the schema via sql keeps the testing methodology consistent: do basically whatever you want to the db, exercise it, restore it.
Raj More's answer got me started. I was hoping someone could short circuit the processes.
Figured I'd share what I ultimately came up with. This script creates a cursor to loop over the tables in the db's INFORMATION_SCHEMA. It does 3 passes over the tables dopping Foreign Keys, then Primary Keys, and finally the tables themselves. Its based on Raj More's idea and considers devio's comment.
-- Helper Procedure
CREATE PROC #DropConstraints
#tableSchema nvarchar(max),
#tableName nvarchar(max),
#constraintType nvarchar(20)
AS
BEGIN
DECLARE #cName nvarchar(max);
DECLARE constraint_cursor CURSOR FOR
SELECT CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE
CONSTRAINT_TYPE = #constraintType
AND TABLE_NAME = #tableName
AND TABLE_SCHEMA = #tableSchema
OPEN constraint_cursor
FETCH NEXT FROM constraint_cursor INTO #cName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('ALTER TABLE ' + #tableSchema + '.' + #tableName + ' DROP CONSTRAINT ' + #cName);
FETCH NEXT FROM constraint_cursor INTO #cName
END
CLOSE constraint_cursor
DEALLOCATE constraint_cursor
END
GO
-- DROP DATABASE TABLES
BEGIN TRANSACTION
DECLARE #tableSchema varchar(max), #tableName varchar(max);
-- Setup Cursor for looping
DECLARE table_cursor SCROLL CURSOR FOR
SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
OPEN table_cursor
-- Drop Foreign Keys
FETCH NEXT FROM table_cursor INTO #tableSchema, #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC #DropConstraints #tableSchema, #tableName, 'FOREIGN KEY';
FETCH NEXT FROM table_cursor INTO #tableSchema, #tableName
END
-- Drop Primary Keys
FETCH FIRST FROM table_cursor INTO #tableSchema, #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC #DropConstraints #tableSchema, #tableName, 'PRIMARY KEY';
FETCH NEXT FROM table_cursor INTO #tableSchema, #tableName
END
-- Drop Tables
FETCH FIRST FROM table_cursor INTO #tableSchema, #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('DROP TABLE ' + #tableSchema + '.' + #tableName);
FETCH NEXT FROM table_cursor INTO #tableSchema, #tableName
END
-- Cleanup
CLOSE table_cursor
DEALLOCATE table_cursor
COMMIT TRANSACTION
GO
You can use the INFORMATION_SCHEMA set of views to generate SQL Scripts to drop all the objects.
You don't have to drop items like indices, triggers, constraints, because they get dropped when you drop the table that they are attached to.
Brute Force Alert
Now tables themselves are tricky because of relationships.
If you separate each drop statement with a GO, you can keep running the script until you have no errors, and then you will have a clean slate.
UnbruteForcing based on feedback
Now, if delete all the foreign keys first, then you can drop all tables in a single go.
I am trying to reduce fragmentation in all of the indexes for a database running on SQL Server 2005.
Currently I am trying to use ALTER INDEX in conjunction with sp_MSforeachtable, to apply it to all of the indexes for all of the tables:
sp_MSforeachtable "ALTER INDEX ALL ON ? REBUILD;"
But for some reason this doesn’t always seem to work?
If I try it for a single index, or all of the indexes for a single table then the fragmentation is cleaned up, it just seems to be when I apply it to the whole database that I get problems.
Previously I might have used DBCC DBREINDEX but BOL states it will be removed in the next version of SQL Server, so I don’t want to use it.
Can anyone give me any advice on the best way to tackle cleaning up all of the indexes in a database?
Thanks
If you want to fully automate your SQL Server Index maintenance then I seriously recommend that you check out Michelle Ufford's stored procedure for this.
Index Defrag Script V4.1
It is what I consider to be the best index maintenance script I have ever read.
One of the best features about this script are that you can customize the threshold values that you use in order to determine whether or not to REBUILD or REORGANIZE a given index strucutre.
It also provides the option to limit the number of CPU cores that are utilized by the procedure. An excellent option if you intend to run the script on a busy live production database.
Warning: As with all internet available code, be sure you test it thoroughly before using in a production environment. You will also most likely want to incorporate your own customisation and features too.
Check out the article and accompanying sample script to handle this task at SQL Fool (Michelle Ufford's website):
http://sqlfool.com/2009/06/index-defrag-script-v30/
This is quite a nice solution to handle this once and for all!
The best practice recommendation is to reorganize your index if you have 5-30% of fragmentation, and only rebuild it if it has more than 30% fragmentation. You can easily use these thresholds or specify your own using this script.
Marc
Or you can use Microsoft's index rebuilding script found here http://msdn.microsoft.com/en-us/library/ms188917.aspx
-- Ensure a USE <databasename> statement has been executed first.
SET NOCOUNT ON;
DECLARE #objectid int;
DECLARE #indexid int;
DECLARE #partitioncount bigint;
DECLARE #schemaname nvarchar(130);
DECLARE #objectname nvarchar(130);
DECLARE #indexname nvarchar(130);
DECLARE #partitionnum bigint;
DECLARE #partitions bigint;
DECLARE #frag float;
DECLARE #command nvarchar(4000);
-- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function
-- and convert object and index IDs to names.
SELECT
object_id AS objectid,
index_id AS indexid,
partition_number AS partitionnum,
avg_fragmentation_in_percent AS frag
INTO #work_to_do
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;
-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;
-- Open the cursor.
OPEN partitions;
-- Loop through the partitions.
WHILE (1=1)
BEGIN;
FETCH NEXT
FROM partitions
INTO #objectid, #indexid, #partitionnum, #frag;
IF ##FETCH_STATUS < 0 BREAK;
SELECT #objectname = QUOTENAME(o.name), #schemaname = QUOTENAME(s.name)
FROM sys.objects AS o
JOIN sys.schemas as s ON s.schema_id = o.schema_id
WHERE o.object_id = #objectid;
SELECT #indexname = QUOTENAME(name)
FROM sys.indexes
WHERE object_id = #objectid AND index_id = #indexid;
SELECT #partitioncount = count (*)
FROM sys.partitions
WHERE object_id = #objectid AND index_id = #indexid;
-- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding.
IF #frag < 30.0
SET #command = N'ALTER INDEX ' + #indexname + N' ON ' + #schemaname + N'.' + #objectname + N' REORGANIZE';
IF #frag >= 30.0
SET #command = N'ALTER INDEX ' + #indexname + N' ON ' + #schemaname + N'.' + #objectname + N' REBUILD';
IF #partitioncount > 1
SET #command = #command + N' PARTITION=' + CAST(#partitionnum AS nvarchar(10));
EXEC (#command);
PRINT N'Executed: ' + #command;
END;
-- Close and deallocate the cursor.
CLOSE partitions;
DEALLOCATE partitions;
-- Drop the temporary table.
DROP TABLE #work_to_do;
GO
I use this script together with SQL Server Agent to automate the task. Hope this helps.
The safest and most portable way is to drop the indices and to re-add them.