Архив

Архив рубрики ‘SQL Server’

Index Defrag Script

IC322Замечательный на мой взгляд скрипт для решения задачи обслуживания индексов баз данных MS SQL Server® опубликовал Michelle Ufford в своем блогеIndex Defrag Script, v4.0.
Скрипт достаточно интеллектуален, автоматически определяет необходимость перестроения или дефрагментации индексов, имеет множество параметров и может быть достаточно тонко настроен для дефрагментации одного или более индексов в одной или более баз данных.

Скачать скрипт.

Применимо: Microsoft SQL Server 2005 SP2 и выше.

Рубрики:SQL Server

Электронная книга Introducing Microsoft SQL Server 2008

Доступна для свободного скачивания электронная книгаms_sql_srv_cvr Introducing Microsoft SQL Server 2008

by Peter DeBetta, Greg Low, and Mark Whitehorn
ISBN: 9780735625587

Learn about major new features in SQL Server 2008 including security, administration, and performance.

Introducing Microsoft SQL Server 2008:
Chapter 1: Security and Administration
Chapter 2: Performance
Chapter 3: Type System
Chapter 4: Programmability
Chapter 5: Storage
Chapter 6: Enhancements for High Availability
Chapter 7: Business Intelligence Enhancements

Скачать

Рубрики:SQL Server

Список версий SQL Server от SQL Server 6.5 до наших дней

Рубрики:SQL Server

Снимок учетных записей в SQL Server

SQL%20Server%20generic%20brand%20Grid%20h Как заскриптовать все логины на SQL Server, их серверные роли + пользователей с правами в базе данных?

SQL Server MVP Алексей Князев попробовал решить эту задачу и его заявка на победу :) тут – Снимок УЗ в SQL Server , в его блоге T-SQL.RU.

За основу взят скрипт от microsoft (http://support.microsoft.com/kb/918992/ru), плюс немного интеллектуального труда и вот цитата T-SQL кодом из его блога:
———————————————
USE master

GO

IF OBJECT_ID (‘sp_hexadecimal’) IS NOT NULL

  DROP PROCEDURE sp_hexadecimal

GO

CREATE PROCEDURE sp_hexadecimal

    @binvalue varbinary(256),

    @hexvalue varchar (514) OUTPUT

AS

DECLARE @charvalue varchar (514)

DECLARE @i int

DECLARE @length int

DECLARE @hexstring char(16)

SELECT @charvalue = ’0x’

SELECT @i = 1

SELECT @length = DATALENGTH (@binvalue)

SELECT @hexstring = ’0123456789ABCDEF’

WHILE (@i <= @length)

BEGIN

  DECLARE @tempint int

  DECLARE @firstint int

  DECLARE @secondint int

  SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))

  SELECT @firstint = FLOOR(@tempint/16)

  SELECT @secondint = @tempint – (@firstint*16)

  SELECT @charvalue = @charvalue +

    SUBSTRING(@hexstring, @firstint+1, 1) +

    SUBSTRING(@hexstring, @secondint+1, 1)

  SELECT @i = @i + 1

END

 

SELECT @hexvalue = @charvalue

GO

 

IF OBJECT_ID (‘sp_help_revlogin_with_roles’) IS NOT NULL

  DROP PROCEDURE sp_help_revlogin_with_roles

GO

CREATE PROCEDURE sp_help_revlogin_with_roles @login_name sysname = NULL AS

DECLARE @name sysname

DECLARE @type varchar (1)

DECLARE @hasaccess int

DECLARE @denylogin int

DECLARE @is_disabled int

DECLARE @PWD_varbinary  varbinary (256)

DECLARE @PWD_string  varchar (514)

DECLARE @SID_varbinary varbinary (85)

DECLARE @SID_string varchar (514)

DECLARE @tmpstr  varchar (1024)

DECLARE @is_policy_checked varchar (3)

DECLARE @is_expiration_checked varchar (3)

 

DECLARE @defaultdb sysname

 

DECLARE @srvrolemember sysname

DECLARE @str varchar(max)

 

IF (@login_name IS NULL)

  DECLARE login_curs CURSOR FOR

 

      SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM

sys.server_principals p LEFT JOIN sys.syslogins l

      ON ( l.name = p.name ) WHERE p.type IN ( ‘S’, ‘G’, ‘U’ ) AND p.name <> ‘sa’

ELSE

  DECLARE login_curs CURSOR FOR

 

      SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM

sys.server_principals p LEFT JOIN sys.syslogins l

      ON ( l.name = p.name ) WHERE p.type IN ( ‘S’, ‘G’, ‘U’ ) AND p.name = @login_name

OPEN login_curs

 

FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin

IF (@@fetch_status = -1)

BEGIN

  PRINT ‘Имена не найдены.’

  CLOSE login_curs

  DEALLOCATE login_curs

  RETURN -1

END

SET @tmpstr = ‘/* sp_help_revlogin script ‘

PRINT @tmpstr

SET @tmpstr = ‘** Generated ‘ + CONVERT (varchar, GETDATE()) + ‘ on ‘ + @@SERVERNAME + ‘ */’

PRINT @tmpstr

PRINT ”

WHILE (@@fetch_status <> -1)

BEGIN

  IF (@@fetch_status <> -2)

  BEGIN

    PRINT ”

    SET @tmpstr = ‘– Login: ‘ + @name

    PRINT @tmpstr

 

    SET @tmpstr = ‘IF EXISTS (SELECT * FROM sys.server_principals WHERE name= ‘ + QUOTENAME( @name , ””) + ‘ ) DROP LOGIN  ‘ + QUOTENAME( @name ) +’;’

    PRINT @tmpstr

 

    IF (@type IN ( ‘G’, ‘U’))

    BEGIN — NT authenticated account/group

 

      SET @tmpstr = ‘CREATE LOGIN ‘ + QUOTENAME( @name ) + ‘ FROM WINDOWS WITH DEFAULT_DATABASE = [' + @defaultdb + ']‘

    END

    ELSE BEGIN — SQL Server authentication

        — obtain password and sid

            SET @PWD_varbinary = CAST( LOGINPROPERTY( @name, ‘PasswordHash’ ) AS varbinary (256) )

        EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT

        EXEC sp_hexadecimal @SID_varbinary, @SID_string OUT

 

        — obtain password policy state

        SELECT @is_policy_checked = CASE is_policy_checked WHEN 1 THEN ‘ON’ WHEN 0 THEN ‘OFF’ ELSE NULL END FROM sys.sql_logins WHERE name = @name

        SELECT @is_expiration_checked = CASE is_expiration_checked WHEN 1 THEN ‘ON’ WHEN 0 THEN ‘OFF’ ELSE NULL END FROM sys.sql_logins WHERE name = @name

 

            SET @tmpstr = ‘CREATE LOGIN ‘ + QUOTENAME( @name ) + ‘ WITH PASSWORD = ‘ + @PWD_string + ‘ HASHED, SID = ‘ + @SID_string + ‘, DEFAULT_DATABASE = [' + @defaultdb + ']‘

 

        IF ( @is_policy_checked IS NOT NULL )

        BEGIN

          SET @tmpstr = @tmpstr + ‘, CHECK_POLICY = ‘ + @is_policy_checked

        END

        IF ( @is_expiration_checked IS NOT NULL )

        BEGIN

          SET @tmpstr = @tmpstr + ‘, CHECK_EXPIRATION = ‘ + @is_expiration_checked

        END

    END

    IF (@denylogin = 1)

    BEGIN — login is denied access

      SET @tmpstr = @tmpstr + ‘; DENY CONNECT SQL TO ‘ + QUOTENAME( @name )

    END

    ELSE IF (@hasaccess = 0)

    BEGIN — login exists but does not have access

      SET @tmpstr = @tmpstr + ‘; REVOKE CONNECT SQL TO ‘ + QUOTENAME( @name )

    END

    IF (@is_disabled = 1)

    BEGIN — login is disabled

      SET @tmpstr = @tmpstr + ‘; ALTER LOGIN ‘ + QUOTENAME( @name ) + ‘ DISABLE;’

    END

    PRINT @tmpstr

  END

 

            –sp_addsrvrolemember

            DECLARE srvrolemember_curs CURSOR FOR

                             SELECT r.name FROM sys.server_role_members rm

                             INNER JOIN

                             sys.server_principals r ON rm.role_principal_id=r.principal_id

                             INNER JOIN

                             sys.server_principals p ON rm.member_principal_id=p.principal_id

                             WHERE p.name=@name

            OPEN srvrolemember_curs

            FETCH NEXT FROM srvrolemember_curs INTO @srvrolemember

            WHILE (@@fetch_status <> -1)

            BEGIN

            IF (@@fetch_status <> -2)

            BEGIN

            SET @tmpstr = ‘EXEC sp_addsrvrolemember ‘ + QUOTENAME( @name ) + ‘, ‘+ QUOTENAME( @srvrolemember ) + ‘;’

            PRINT @tmpstr

            END

            FETCH NEXT FROM srvrolemember_curs INTO @srvrolemember

            END

            CLOSE srvrolemember_curs

            DEALLOCATE srvrolemember_curs

 

            –CREATE USERS

            set @str=’USE ?

            IF EXISTS (SELECT * FROM sys.database_principals WHERE sid=’+

            CONVERT (VARCHAR(514), @SID_varbinary, 1)+’)

            BEGIN

            DECLARE @name sysname, @schema sysname

            SELECT @name=name, @schema=default_schema_name FROM sys.database_principals WHERE sid=’+

            CONVERT (VARCHAR(514), @SID_varbinary, 1)+

            ‘print "USE ?;

            IF EXISTS (SELECT * FROM sys.database_principals WHERE name=”"+@name+"”)

            DROP USER "+QUOTENAME(@name)+";

            CREATE USER "+QUOTENAME(@name)+" FOR LOGIN ‘+ QUOTENAME( @name ) +’ WITH DEFAULT_SCHEMA = "+QUOTENAME(@schema)+";"

 

                  DECLARE @dbrolemember sysname

                  DECLARE dbrolemember_curs CURSOR FOR

                  SELECT r.name FROM sys.database_role_members rm

                  INNER JOIN

                  sys.database_principals r ON rm.role_principal_id=r.principal_id

                  INNER JOIN

                  sys.database_principals p ON rm.member_principal_id=p.principal_id

                  WHERE p.name=@name

                  OPEN dbrolemember_curs

                  FETCH NEXT FROM dbrolemember_curs INTO @dbrolemember

                  WHILE (@@fetch_status <> -1)

                  BEGIN

                  IF (@@fetch_status <> -2)

                  BEGIN

                  PRINT "EXEC sp_addrolemember "+QUOTENAME(@dbrolemember)+", "+QUOTENAME(@name)+";"

                  END

                  FETCH NEXT FROM dbrolemember_curs INTO @dbrolemember

                  END

                  CLOSE dbrolemember_curs

                  DEALLOCATE dbrolemember_curs

            END

            ‘

            EXECUTE sp_MSforeachdb @str

 

  FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin

   END

CLOSE login_curs

DEALLOCATE login_curs

RETURN 0

GO
———————————————

Сценарий создает в базе данных master две хранимых процедуры — sp_hexadecimal и sp_help_revlogin_with_roles.
Далее вызываем процедуру и получаем скрипт-снимок состояния УЗ на сервере БД:

———————————————
EXEC
master..sp_help_revlogin_with_roles
———————————————

 
Применимо:
SQL Server 2005 и выше

Рубрики:SQL Server

MCP-Club Самара. SQL Server 2008. Планирование установки, настройка для наилучшей производительности.

j0439328 В июле проходила очередная встреча Самарского MCP-Клуба. Я читал доклад на тему “SQL Server 2008. Планирование установки, настройка для наилучшей производительности”.

Презентацию в формате PowerPoint можно скачать здесь.

Рубрики:SQL Server

SQL Server 2005, 2008: Создание недостающих индексов

speedometer-thumbВ SQL Server начиная с версии 2005 есть функция отсутствующих индексов, которая использует объекты DMO и классы событий Showplan для получения сведений об отсутствующих индексах, благодаря которым можно повысить производительность обработки запросов в SQL Server.

А как получить эти сведения, обработать и принять решение о необходимости создания тех или иных индексов?

Интересная методика представлена в Учебном курсе Microsoft “SQL Server 2005 Реализация и обслуживание”.
Решение о эффективности индекса предлагается принять из расчета некоторого значения по формуле user_seeks * avg_total_user_cost * (avg_user_impact * 0.01). Исходные данные для расчета берутся из представлений sys.dm_db_missing_index*.
Значение выше 5000 в промышленных системах означает, что следует рассмотреть возможность создания этих индексов.
Если же значение превышает 10000, это обычно означает, что индекс может обеспечить значительное повышение производительности для операций чтения.
Немного творчества и получаем вот такой скрипт:
——————————————————————————————–
– Создание недостающих индексов баз данных на SQL Server 2005, 2008

– Скрипт анализирует статистику, собранную сервером баз данных об отсутствующих индексах в базах данных и
– предлагает создать индексы, которые могут обеспечить значительное повышение производительности. 

SET NOCOUNT ON

DECLARE @dbid int

 

IF (object_id(‘tempdb..##IndexAdvantage’) IS NOT NULL) DROP TABLE ##IndexAdvantage

CREATE TABLE ##IndexAdvantage ([Преимущество индекса] float, [База данных] varchar(64), [Transact SQL код для создания индекса] varchar(512),

[Число компиляций] int, [Количество операций поиска] int, [Количество операций просмотра] int,

[Средняя стоимость ] int, [Средний процент выигрыша] int );

 

DECLARE DBases CURSOR FOR

SELECT database_id FROM sys.master_files Получаем список ID баз данных 

WHERE state = 0 AND – ONLINE

has_dbaccess(db_name(database_id)) = 1 – Only look at databases to which we have access

GROUP BY database_id

 

OPEN DBases

FETCH NEXT FROM DBases

INTO @dbid

 

WHILE @@FETCH_STATUS = 0

BEGIN – Выполняем для каждой базы данных ————————————————–

 

INSERT INTO ##IndexAdvantage

SELECT [Преимущество индекса] = user_seeks * avg_total_user_cost * (avg_user_impact * 0.01),

      [База данных] = DB_NAME(mid.database_id),

      [Transact SQL код для создания индекса] = ‘CREATE INDEX [IX_' + OBJECT_NAME(mid.object_id,@dbid) + '_' +

      CAST(mid.index_handle AS nvarchar) + '] ON ‘ +

      mid.statement + ‘ (‘ + ISNULL(mid.equality_columns,) +

      (CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ‘, ‘ ELSE END) +

      (CASE WHEN mid.inequality_columns IS NOT NULL THEN + mid.inequality_columns ELSE END) +

      ‘)’ +

      (CASE WHEN mid.included_columns IS NOT NULL THEN ‘ INCLUDE (‘ + mid.included_columns + ‘)’ ELSE END) +

      ‘;’,

      [Число компиляций] = migs.unique_compiles,

      [Количество операций поиска] = migs.user_seeks,

      [Количество операций просмотра] = migs.user_scans,

      [Средняя стоимость ] = CAST(migs.avg_total_user_cost AS int),

      [Средний процент выигрыша] = CAST(migs.avg_user_impact AS int)

FROM  sys.dm_db_missing_index_groups mig

JOIN  sys.dm_db_missing_index_group_stats migs

ON    migs.group_handle = mig.index_group_handle

JOIN  sys.dm_db_missing_index_details mid

ON    mig.index_handle = mid.index_handle

AND   mid.database_id = @dbid

 

    FETCH NEXT FROM DBases

    INTO @dbid

END —————————————————————————————-

CLOSE DBases

DEALLOCATE DBases

GO

 

SELECT * FROM ##IndexAdvantage ORDER BY 1 DESC

– Значение ”Преимущество индекса” выше 5000 в промышленных системах означает, что следует рассмотреть возможность создания этих индексов.

– Если же значение превышает 10000, это обычно означает, что индекс может обеспечить значительное повышение производительности для операций чтения.

——————————————————————————————–

– Отправляем email с рекомендацией создать индекс

IF (object_id(‘tempdb..##IndexAdvantage2′) IS NOT NULL) DROP TABLE ##IndexAdvantage2

SELECT * INTO ##IndexAdvantage2 FROM ##IndexAdvantage WHERE [Преимущество индекса] >= 5000 ORDER BY 1 DESC

 

IF ((SELECT COUNT(*) FROM ##IndexAdvantage2) >= 1) BEGIN

DECLARE @subject_str varchar(255),

@message_str varchar(1024),

@separator_str varchar(1),

@email varchar(128)

 

SET @separator_str=CHAR(9) – Символ табуляции

SET @email = ‘email_address@webzavod.ru’

 

– Подготовим текст сообщения

SET @subject_str = ‘SQL Server ‘+@@SERVERNAME+‘: Предложение создать индексы в базе данных.’

SET @message_str = ‘Сервер ‘+@@SERVERNAME + ‘. Выявлена необходимость создать индексы в базе данных!

Во вложении – таблица с кодом предлагаемых индексов.

Значение “Преимущество индекса” выше 5000 в промышленных системах означает, что следует рассмотреть возможность создания этих индексов.

Если же значение превышает 10000, это обычно означает, что индекс может обеспечить значительное повышение производительности для операций чтения.

Динамические административные представления, которые помогли нам получить информацию об отсутствующих индексах, не являются заменой помощника по настройке ядра СУБД, который также рассматривает индексированные представления и секции и обеспечивает более всесторонний анализ индексов, но они могут быть очень эффективны на начальном уровне анализа.’

 

Отправляем email

EXEC msdb.dbo.sp_send_dbmail

@recipients = @email,

@query = ‘SELECT * FROM ##IndexAdvantage2′,

@subject = @subject_str,

@body = @message_str,

@attach_query_result_as_file = 1,

@query_result_separator = @separator_str,

@query_result_width = 7000

END

 

– Удаляем временную таблицу

IF (object_id(‘tempdb..##IndexAdvantage’) IS NOT NULL) DROP TABLE ##IndexAdvantage

IF (object_id(‘tempdb..##IndexAdvantage2′) IS NOT NULL) DROP TABLE ##IndexAdvantage2
——————————————————————————————–

Как использовать данный скрипт:
Можно создать JOB на основе этого скрипта и выполнять его периодически.
Если скрипт выявит необходимость создать какой либо индекс, то он сообщит Вам об этом, послав электронное письмо (компонент Database Mail должен быть включен и настроен).

Отмечу также, что если приложение само управляет объектами базы данных, то и индексы следует создавать через функционал данного приложения.
Пример такого приложения –
Microsoft Dynamics AX.

Пример результата:

В прикрепленном файле образец предложения индекса данным скриптом. База данных от Microsoft Dynamics CRM 3.0
QueryResults897901.txt

Рубрики:SQL Server

SQL Server 2005: Определение ценности предложенных индексов

Определить ценность предложенных не существующих индексов в базах данных на SQL Server 2005 можно следующим скриптом:

SELECT * FROM

(SELECT user_seeks * avg_total_user_cost * (avg_user_impact * 0.01) AS index_advantage,

migs.* FROM sys.dm_db_missing_index_group_stats migs) AS migs_adv

INNER JOIN sys.dm_db_missing_index_groups AS mig ON migs_adv.group_handle = mig.index_group_handle

INNER JOIN sys.dm_db_missing_index_details AS mid ON mig.index_handle = mid.index_handle

ORDER BY migs_adv.index_advantage

 

Значение выше 5000 в промышленных системах означает, что следует рассмотреть возможность создания этих индексов. Если же значение превышает 10000, это обычно означает, что индекс может обеспечить значительное повышение производительности для операций чтения.

 

Динамические административные представления, которые помогли нам получить информацию об отсутствующих индексах, не являются заменой помощника по настройке ядра СУБД, который также рассматривает индексированные представления и секции и обеспечивает более всесторонний анализ индексов, но они могут быть очень эффективны на начальном уровне анализа.

 

Чтобы сгенерировать код для создания индекса, можно воспользоваться скриптом Александра Гладченко, описанном в его блоге Tips for DBA: Missing indexes recommendations (SQL Server 2005):

 

    SELECT [Рекомендуемый индекс]= '-- CREATE INDEX [IX_' + OBJECT_NAME(mid.object_id) + '_' + CAST(mid.index_handle AS nvarchar) + '] ON ' + mid.statement + ' (' + ISNULL(mid.equality_columns,'') + ', ' + ISNULL(mid.inequality_columns,'') + ') INCLUDE (' + ISNULL(mid.included_columns,'') + ');', [Число компиляций] = migs.unique_compiles, [Количество операций поиска] = migs.user_seeks, [Количество операций просмотра] = migs.user_scans, [Средняя стоимость ] = CAST(migs.avg_total_user_cost AS int), [Средний процент выигрыша] = CAST(migs.avg_user_impact AS int) FROM sys.dm_db_missing_index_groups mig JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle AND mid.database_id = DB_ID()

Рубрики:SQL Server

Оповещение о наличии длительной блокировки на SQL Server

Встал как то вопрос о том чтобы последить за длительными блокировками на SQL Server 2000.
Такие блокировки могут быть как от действительно длительных и очень длительных (возможно "кривых" запросов) процессов, так и от "зависших" пользовательских процессов.
Можно например запустив Enterprise Manager посмотреть Current Activity и увидеть очередь возникших блокировок, иногда EM задумывается на этом процессе неприемлемо долго.
Можно в Query Analyzer выполнить хранимую процедуру sp_who2 и также определить очередь и блокирующий(ие) процессы.
А как сделать так, чтобы ничего не делать? :) – правильно – автоматизировать.

Родился нижележащий скрипт.
Создаем на его основе джоб, периодически выполняем, периодически получаем уведомление на email оповещение о длительной блокировке.

Не продакшен версия конечно, но кому пригодится – черкните.
===================================================================
–Оповещение о наличии длительной блокировки на сервере
– Отправляем email в случае обнаружения длительной блокировки

SET NOCOUNT ON
– Создадим переменные
DECLARE @LimitWaitTime int,
@MaxWaitTime int,
@SPID smallint,
@subject_str varchar(255),
@message_str varchar(255),
@separator_str varchar(1),
@email varchar(128)

– Определим значения переменных
SET @LimitWaitTime=300000 — Максимальное время в милисекундах ожидания в очереди блокировок, при превышении которого отсылаем email (типа признак ДЛИТЕЛЬНОЙ блокировки)
SET @separator_str=CHAR(9) — Символ табуляции
SET @email = ‘events@vesna.ru’

– создаем временную таблицу для хранения информации от sp_who2
IF (object_id(‘tempdb..#t1′) IS not null) DROP TABLE #t1
IF (object_id(‘tempdb..##t2′) IS not null) DROP TABLE ##t2
CREATE TABLE #t1 (SPID smallint, Status varchar(30), Login varchar(128), HostName varchar(128), BlkBy varchar(5), DBName varchar(128), Command varchar(16), CPUTime int, DiskIO bigint, LastBatch varchar(128), ProgramName varchar(128), SPID2 smallint);

– Выполняем и сохраняем результат sp_who2
INSERT INTO #t1 EXECUTE (‘sp_who2′)

– Дополняем результат sp_who2 данными о WaitTime
– Некоторые длинные поля немного урезаем SUBSTRING-ом для приемлемого вида
SELECT
tbl1.SPID,
SUBSTRING(tbl1.Status,1,15) AS Status,
SUBSTRING(Login,1,25) AS Login,
SUBSTRING(tbl1.HostName,1,15) AS HostName,
BlkBy, SUBSTRING(DBName,1,15) AS DBName,
SUBSTRING(Command,1,35) AS Command,
CPUTime,
DiskIO,
SUBSTRING(LastBatch,1,15) AS LastBatch,
SUBSTRING(ProgramName,1,60) AS ProgramName,
WaitTime
INTO ##t2
FROM #t1 AS tbl1 LEFT OUTER JOIN master..sysprocesses AS tbl2 WITH (NOLOCK) ON tbl1.SPID = tbl2.SPID
WHERE tbl1.SPID IN (SELECT BlkBy FROM #t1 WHERE BlkBy not like ‘%.%’) OR BlkBy not like ‘%.%’

– Удаляем временную таблицу
IF (object_id(‘tempdb..#t1′) IS not null) DROP TABLE #t1

– Максимальное время ожидания в очереди блокировок
SELECT @MaxWaitTime=MAX(WaitTime) FROM ##t2
SELECT @MaxWaitTime AS [Максимальное время ожидания (мсек)]

– Блокирующий процесс
SELECT @SPID=SPID FROM ##t2 WHERE BlkBy like ‘%.%’
SELECT @SPID AS [Блокирующий SPID]
SELECT DISTINCT * FROM ##t2

– Отправляем email оповещение об обнаружении ДЛИТЕЛЬНОЙ блокировки
IF (@MaxWaitTime>@LimitWaitTime) BEGIN

– Подготовим текст сообщения
SET @subject_str = ‘SQL Server ‘+@@SERVERNAME+’: Длительная блокировка! (SPID:’+convert(varchar(5),@SPID)+’)’
SET @message_str = ‘Обнаружена длительная блокировка!

Сервер ‘+@@SERVERNAME+’
Идентификатор процесса (SPID) = ‘+convert(varchar(5),@SPID)+’,
Максимальное время ожидания в очереди блокировок = ‘+convert(varchar(5),@MaxWaitTime/60000)+’ мин.,

Примите меры!’

– Отправляем email
EXEC xp_sendmail @recipients = @email,
@query = ‘SELECT * FROM ##t2′,
@subject = @subject_str,
@message = @message_str,
@attachments = ‘sp_who2.txt’,
@attach_results = ‘TRUE’,
@width = 1024,
@separator = @separator_str
–,@no_header= ‘TRUE’
END

– Удаляем временную таблицу
IF (object_id(‘tempdb..##t2′) IS not null) DROP TABLE ##t2
===================================================================

Применимо:
MS SQL Server 2000

Рубрики:SQL Server

Необходимо ли в Windows Server 2008 выравнивание кластеров NTFS и блоков RAID массива?

В моем предыдущем сообщении – Выравнивание кластеров NTFS и блоков RAID массива (детальный тест для SQL Server) Илья Сазонов (sie) оставил комментарий о том что затронутые проблемы с выравниванием наблюдались в операционных системах Windows Server 2003 (и Windows XP), но не существуют в Windows Server 2008 и Windows Vista – там сдвиг изначально кратен 1024.

Проверяем..

На виртуальной машине установлен Windows Server 2008 Core, раздел создавался мастером установки.

image

Да, действительно, смещение равно 1024Kb.

Несомненно это еще один плюс в копилку Windows Server 2008!

Спасибо Илья, за ваш ценный комментарий!

Рубрики:SQL Server

Выравнивание кластеров NTFS и блоков RAID массива (детальный тест для SQL Server )

По мотивам статьи Tips for DBA: выравнивание кластеров NTFS и блоков RAID-массивов Александра Гладченко.
Выравнивание размеров кластеров файловой системы и блоков RAID массива позволит увеличить производительность дисковых операций. – А на сколько и на каких операциях?
Я решил сам проверить это! – Это будет Честный детект.. Потестируем..
Цель теста:
Измерить прирост производительности дисковой подсистемы в контексте дисковых операций MS SQL Server и оценить степень этого прироста.
Материальное обеспечение теста:
- Сервер HP DL560 G1 2 CPU, 4GB RAM, Windows Server 2003 R2 SP2 Standard;
- Дисковый массив HP MSA 1000;
- 4 диска Ultra SCSI 320 300GB 10K;
I. Калибровка дисков
Задача: На этом этапе мы должны убедиться, что используемые диски работоспособны, определить разброс скоростей чтения и записи по дискам, чтобы потом учитывать возможности каждого диска при распределении дисков в массивах.
Поскольку диски с повреждениями или существенными отклонениями от средней производительности, скорее всего, ведут себя одинаково плохо под разными типами рабочей нагрузки, а также потому, что дальнейшее тестирование также может выявить проблемные диски, мы ограничимся одним, грубым тестом. Для проведения этого калибровочного теста необходимы следующие подготовительные действия:
1. С помощью поставляемых с дисковым контроллером HP MSA 1000 специализированных утилит, установленных на сервере, конфигурируем все диски полки как 4 массива RAID0, каждый из которых состоит из одного диска, размер каждого массива выбирается равным всему доступному размеру диска, размер блока низкоуровневой разметки выбираем равным 64Кб, для чистоты измерений кэширование чтения и записи для этих дисков отключаем.
2. С помощью оснастки управления дисками, входящей в состав mmc-консоли управления компьютером, создаем для каждого физического диска полки RAW-раздел (без форматирования NTFS) величиной на весь диск, и без присвоения буквы диска (буквы присваивать можно, но это не обязательно).
3. Установить программу SQLIO Disk Subsystem Benchmark Tool. Везде по тексту настоящей статьи местоположение программы sqlio.exe выбрано следующее: C:\SQLIO\sqlio.exe
Более подробно об утилите можно узнать в статье –
Эталонный тест дисковой подсистемы SQLIO.
4. Подготовим командный файл, который будет запускать программу sqlio.exe в разных режимах для каждого диска и сохранять результаты в файлы. Текст командного файла:
——————————————
sqlio -kR -s300 -b64 -f1 -i4200000 -o1 -t1 -R1 -LP -a2 -BN > R01-b64-f1-i4200000-o1-t1.log
timeout /T 30
sqlio -kW -s300 -b64 -f1 -i4200000 -o1 -t1 -R1 -LP -a2 -BN > W01-b64-f1-i4200000-o1-t1.log
timeout /T 30
sqlio -kR -s300 -b64 -f1 -i4200000 -o1 -t1 -R3 -LP -a2 -BN > R03-b64-f1-i4200000-o1-t1.log
timeout /T 30
sqlio -kW -s300 -b64 -f1 -i4200000 -o1 -t1 -R3 -LP -a2 -BN > W03-b64-f1-i4200000-o1-t1.log
timeout /T 30
sqlio -kR -s300 -b64 -f1 -i4200000 -o1 -t1 -R4 -LP -a2 -BN > R04-b64-f1-i4200000-o1-t1.log
timeout /T 30
sqlio -kW -s300 -b64 -f1 -i4200000 -o1 -t1 -R4 -LP -a2 -BN > W04-b64-f1-i4200000-o1-t1.log
timeout /T 30
sqlio -kR -s300 -b64 -f1 -i4200000 -o1 -t1 -R5 -LP -a2 -BN > R05-b64-f1-i4200000-o1-t1.log
timeout /T 30
sqlio -kW -s300 -b64 -f1 -i4200000 -o1 -t1 -R5 -LP -a2 -BN > W05-b64-f1-i4200000-o1-t1.log
——————————————
В этом файле каждый вызов программы sqlio.exe имеет одинаковые аргументы, кроме аргумента R, который имеет значения 1, 3, 4, 5 – номера дисков согласно консоли “Управление дисками”. Каждый диск тестируется на чтение и, после 30 секундной паузы, на запись (аргумент k). Время тестирования каждого диска 300 секунд (аргумент s), размер блока 64Кб (аргумент b), Число блоков в строке равно единице (аргумент f), число строк равно 4200000 (аргумент i), число очередей тоже равно единице (аргумент o), число потоков равно единице (аргумент t). Суммарный размер файла рабочей нагрузки на каждом диске составляет ~270Гб, что почти совпадает с размером диска.

Образец вывода программы sqlio.exe
——————————————
sqlio v1.5.SG
calibrating timestamp counter for latency timings… done (MHz measured at 2956)
1 thread reading for 300 secs from file 5:
using 64KB IOs over 64KB stripes with 4200000 IOs per run
enabling multiple I/Os per thread with 1 outstanding
buffering set to not use file nor disk caches (as is SQL Server)
affinity mask is 0×2 (2)
initialization done
CUMULATIVE DATA:
throughput metrics:
IOs/sec:   843.64
MBs/sec:    52.72
latency metrics:
Min_Latency(ms): 1
Avg_Latency(ms): 1
Max_Latency(ms): 24
histogram:
ms: 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24+
%:  0 100  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
——————————————
5. Запустим командный файл на исполнение, а потом сведем собранные в файлы результаты в общую таблицу, для дальнейшего сравнения и анализа (отберем только интересующие нас данные – метрику “MBs/sec”).
На Рисунке 1 показан результат калибровочного тестирования 4-х дисков.
Rfkb,hjdrf lbcrgп
Рис.1
Наиболее важной задачей нагрузочного тестирования является выявление дисков, характеристики которых существенно отличаются от остальных. На Рисунке 1 диски практически идентичны, как по записи, так и по чтению.
II. Выбор размера блока и уровня RAID
Таблица 1. Характеристики для основных типов нагрузки ввода – вывода SQL Server
image_13
Многие специалисты рекомендуют устанавливать размер блока для форматирования NTFS раздела операционной системы Windows равным 64 Кб и делать такого же размера размер страйпа при монтировании дискового массива. Данная тема многократно обсуждалась во многих источниках.
На этом не задерживаемся – выбираем 64K.
В выборе уровня RAID я остановлюсь на RAID10. Выбор оптимального уровня RAID не цель этой статьи, – это много раз обсуждалось и обсуждается в других источниках.
RAID будет подвержен тестовым сериям измерения скорости чтения и записи, для разных размеров блока. Размер блока (который задаётся параметром –b) будет принимать следующий набор значений: 1024, 512, 256, 128, 64, 8. Размеры блока соответствуют размерам основных типов запросов ввода-вывода.

III. Тест производительности без выравнивания кластеров NTFS и блоков RAID массива

С помощью поставляемых с дисковым контроллером HP MSA 1000 утилит создаем массив RAID10 из четырех имеющихся дисков, размер выбирается максимально доступный, размер блока низкоуровневой разметки выбираем равным 64Кб, кэширование чтения и записи для этого диска отключаем.
С помощью оснастки “Управление дисками”, входящей в состав mmc консоли “Управление компьютером” создаем раздел величиной в весь диск, форматируем в NTFS, с размером кластера 64K.
Диск готов.
Узнаем, для информации, смещение кластеров NTFS на созданном разделе.
image_8
Рис.2
Смещение равно 32K
Запускаем тест (см. командный файл в Приложении 1).
Получаем результаты (см. Рис.4).

IV. Тест производительности с выравниванием кластеров NTFS и блоков RAID массива
RAID10 на дисковой полке остается без изменений с предыдущего теста.
Удаляем раздел из оснастки “Управление дисками”.
Создаем раздел с использованием DISKPART
CREATE PARTITION PRIMARY ALIGN=64
image_10
Рис.3
С помощью оснастки “Управление дисками”, входящей в состав mmc консоли “Управление компьютером” форматируем раздел в NTFS, с размером кластера 64K.
Диск готов. Запускаем тест (см. командный файл в Приложении 1).
Получаем результаты (см. Рис.4).

На рисунке 4 показана сводная таблица с результатами тестов.
image_5
Рис.4
На рисунке 5 показаны результаты тестов в виде графиков.
image_11
Рис. 5
Выводы:
В результате выравнивания кластеров NTFS и блоков RAID массива повышается производительность дисковых операций.
Повышение производительности зафиксировано на операциях чтения и записи блоками по 8K и 64K.
Практически все основные типы нагрузки ввода-вывода SQL Server получили выигрыш от этой оптимизации от 9 до 13%.
Отрицательный и близкий к нулю прирост производительности в таблице результатов тестов можно отнести к погрешностям измерений.
P.S.: Выражаю благодарность Александру Гладченко за оказание помощи методическими материалами.
Приложение 1
Командный файл:
——————————————
sqlio -kW -s180 -frandom -o8 -b8 -LP -BN -Fparam.txt > WR-b8-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -frandom -o8 -b64 -LP -BN -Fparam.txt > WR-b64-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -frandom -o8 -b128 -LP -BN -Fparam.txt > WR-b128-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -frandom -o8 -b256 -LP -BN -Fparam.txt > WR-b256-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -frandom -o8 -b512 -LP -BN -Fparam.txt > WR-b512-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -frandom -o8 -b1024 -LP -BN -Fparam.txt > WR-b1024-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -fsequential -o8 -b8 -LP -BN -Fparam.txt > WS-b8-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -fsequential -o8 -b64 -LP -BN -Fparam.txt > WS-b64-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -fsequential -o8 -b128 -LP -BN -Fparam.txt > WS-b128-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -fsequential -o8 -b256 -LP -BN -Fparam.txt > WS-b256-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -fsequential -o8 -b512 -LP -BN -Fparam.txt > WS-b512-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kW -s180 -fsequential -o8 -b1024 -LP -BN -Fparam.txt > WS-b1024-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -frandom -o8 -b8 -LP -BN -Fparam.txt > RR-b8-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -frandom -o8 -b64 -LP -BN -Fparam.txt > RR-b64-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -frandom -o8 -b128 -LP -BN -Fparam.txt > RR-b128-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -frandom -o8 -b256 -LP -BN -Fparam.txt > RR-b256-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -frandom -o8 -b512 -LP -BN -Fparam.txt > RR-b512-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -frandom -o8 -b1024 -LP -BN -Fparam.txt > RR-b1024-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -fsequential -o8 -b8 -LP -BN -Fparam.txt > RS-b8-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -fsequential -o8 -b64 -LP -BN -Fparam.txt > RS-b64-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -fsequential -o8 -b128 -LP -BN -Fparam.txt > RS-b128-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -fsequential -o8 -b256 -LP -BN -Fparam.txt > RS-b256-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -fsequential -o8 -b512 -LP -BN -Fparam.txt > RS-b512-LP-BN-F(2-0×0-2048).log
timeout /T 30
sqlio -kR -s180 -fsequential -o8 -b1024 -LP -BN -Fparam.txt > RS-b1024-LP-BN-F(2-0×0-2048).log

——————————————
param.txt
——————————————
T:\testfile.dat 2 0×0 2048
——————————————
Рубрики:SQL Server
Follow

Get every new post delivered to your Inbox.

Join 28 other followers