Buffer Pool Extension в SQL Server 2014 часть 4, сравнительное тестирование производительности при обновлении данных

В одной из своих предыдущих статей я уже описывал результаты пробного тестирования производительности операций чтения при использовании BPE. Но в реальной жизни данные нужно не только читать, но и обновлять, поэтому я решил проверить, а может ли BPE также ускорить операции обновления данных. Тут сразу же стоит принять во внимание несколько особенностей, перед тем как проводить тесты. Во-первых, все операции вставки, обновления и удаления логгируемые, а это значит, что возникнет нагрузка на журнал транзакций и многое будет зависеть от дисковой подсистемы, на которой он будет расположен. Поэтому, проведя несколько пробных замеров, я вынес журнал транзакций на SSD диск, чтобы минимизировать его влияние на операции обновления. Во-вторых, перед тем как обновить данные, SQL Server сначала считывает страницу с диска в Buffer Pool, после этого вносит изменения и помечается страницу с данными как «грязную» (dirty). Страница позже будет записана на диск процессами Checkpoint или Lazy Writer, и первый из этих процессов тоже косвенно может повлиять на результаты тестирования, поэтому я его отключил. В-третьих, я написал запрос на изменение данных таким образом, чтобы новые данные были по размеру такими же, как и старые, чтобы не происходило расщепления страниц. В-четвертых, Buffer Pool Extension может хранить только «чистые» страницы, поэтому операции обновления будут «вымывать» данные из него. Но о том, как SQL Server будет вести себя в этой ситуации, чуть позже, а пока расскажу о конфигурации тестового стенда.

Для тестирования я опять буду использовать виртуальную машину с 4 Гб оперативной памяти. Я создал отдельную базу данных с одной таблицей. В таблице всего 2 столбца [id] и [n]. Первый столбец имеет целочисленный тип данных и является первым ключом с кластеризованным индексом на нем. Второй столбец просто выполняет роль каких-то данных в системе.

use [master];
go

create database [BufferPoolExtension_test];
go

use [BufferPoolExtension_test];
go

create table [dbo].[TestTable] (
	[id] int identity(1,1) not null,
	[n] [char](1000) not null,
	
	constraint [PK_TestTable] primary key clustered ([id])
);
go

insert into [dbo].[TestTable] ([n])
values (replicate('A', 1000));
go 1000000

Размер таблицы получается чуть больше 1 Гб и такой размер позволит либо поместить всю таблицу в память, либо только часть, регулируя параметр MAX MEMORY.

Тестирование будет заключаться в том, что я буду выполнять 10000 случайных запросов изменение одной строки данных. В реальной жизни такая нагрузка в чистом виде практически не встречается, а чаще всего совместно со случайными чтениями данных, но нам нужно проверить как будет работать обновление само по себе. Данный запрос я буду выполнять несколько раз и считать среднее арифметическое результатов:

update [dbo].[TestTable]
set [n] = REPLICATE(char(65 + cast(rand(checksum(newid())) * 26 as tinyint)), 1000)
where [id] = cast(rand(checksum(newid())) * 1000000 as int) + 1;
go 10000

Итак, результаты первого теста, когда все данные в оперативной памяти и BPE отключен: 2.7 секунды. Это так называемая идеальная ситуация, когда памяти достаточно и все данные находятся в кэше.

Во втором результате я слегка модифицирую запрос и добавлю в него команду очистки Buffer Pool, чтобы посмотреть на «худший» вариант, когда в кэше нет никаких данных.

dbcc dropcleanbuffers;
go

update [dbo].[TestTable]
set [n] = REPLICATE(char(65 + cast(rand(checksum(newid())) * 26 as tinyint)), 1000)
where [id] = cast(rand(checksum(newid())) * 1000000 as int) + 1;
go 10000

Результат 2 минуты 32 секунды.

Во третьем тесте я ограничу размер максимально доступной памяти для SQL Server до 256 Мб – это почти в 4 раза меньше, чем размер данных и попробую повторить тест. При этом стоит отметить, что во время теста в кэше не находилось больше чем 90 Мб от всех данных в таблице, что составляет примерно только 8% от всего объема. Результат: 2 минуты 29 секунд.

В четвертом тесте я включу Buffer Pool Extension размером 4 Гб и несколько раз сделаю полное сканирование таблицы перед началом теста, чтобы все данные были либо в памяти, либо в BPE. Стоит отметить, что практически все данные размещаются в BPE, т.е. SQL Server старается поместить все чистые страницы туда и не держать их в памяти. И вот тут началось самое интересное – время выполнения тестовой нагрузки колебалось очень сильно: во время первого запуска оно было 22 секунды, потом резко подскочило до 40, а затем и до 55 секунд, еще через пару запусков до минуты с небольшим и на этом месте «замерло». В этот момент в BPE находилось ~75% данных, а в памяти еще около 8%. Дальнейшие запуски продолжили «вымывать» кэш, но время выполнения теста уже колебалось не очень значительно и составляло в среднем 1 минуту 15 секунд. После некоторых тестов я попробовал вручную запустить процесс Checkpoint, чтобы проверить, сможет ли он после записи «грязных» страниц на диск перемещать их снова в BPE, но увы он делал это очень вяло. Но, если при этом попробовать снова запускать нагрузку имитирующую случайные чтения, то данные снова перемещались в BPE.

И последний, пятый тест. Всю базу данных я размещу на SSD диске, отключу BPE и буду очищать кэш каждый раз перед запуском. Результат: 7 секунд.

Итоговая таблица с результатами:

№ теста

Описание теста

Результат, время

1

Все данные находятся в памяти.

2.7 сек.

2

Все данные находятся на диске, (“холодный” кэш, в памяти данных нет).

2 мин. 32 сек.

3

Размер оперативной памяти ограничен. В кэше находится примерно 8% от всего объема данных.

2 мин. 29 сек.

4

Размер оперативной памяти ограничен как в тесте №3, но включен BPE – практически все данные находятся в BPE, а не в памяти.

1 мин. 15 сек. *

5

База данных расположена на SSD, (“холодный” кэш, в памяти данных нет).

7 сек.

 

Итак, какой вывод можно сделать из тестирования. Использование BPE может ускорить случайное изменение данных из таблицы, если памяти недостаточно для полного кэширования таблицы и данные уже присутствуют в BPE. При этом ускорение будет не таким значительным, как при случайном чтении данных. Для OLTP систем характерно то, что процент изменений гораздо меньше, чем чтений, поэтому смешанная нагрузка, например, 80% чтений и 20% обновлений может достаточно хорошо ускорится при использовании BPE.

Buffer Pool Extension в SQL Server 2014 часть 3, мониторинг системы

Попробую рассказать немного о том, какие средства мониторинга доступны в SQL Server 2014, чтобы проводить диагностику и оценивать работу Buffer Pool Extension.

В первую очередь появилось системное представление sys.dm_os_buffer_pool_extension_configuration, которое возвращает информацию о конфигурации BPE. Оно показывает включен или нет BPE, расположение файла и его размер. И хотя из описания следует, что может быть несколько файлов BPE, включить их невозможно, по крайней мере в CTP1. Возможно позже ситуация изменится и описание представления будет доработано.

Также в системное представление sys.dm_os_buffer_descriptors добавляется столбец is_in_bpool_extension, что позволяет получить информацию об отдельных страницах. Т.е. теперь можно получить список отдельных страниц с разрезом по базам данных и по отдельным объектам с учетом, сколько и какие конкретно страницы находятся в BPE. Например, вот такой запрос позволяет увидеть, какой процент страниц базы данных находится в памяти, а какой в BPE.

use [BufferPoolExtension_test];
go

select
	db_name(database_id) as [db_name],
	is_in_bpool_extension,
	cast(count(*) * 100.0 /
		(select count(*) from sys.dm_os_buffer_descriptors where database_id = db_id())
		as decimal(5, 2))	as [buffer pool, %]
from sys.dm_os_buffer_descriptors
where
	database_id = db_id()
group by
	database_id, is_in_bpool_extension;
go

Результат 22% закэшированных страниц в памяти, а остальное в BPE:

Extended Events набирают все большую популярность и для мониторинга BPE доступно 4 события.

XEvent

Описание

sqlserver.buffer_pool_extension_pages_written

Page or contiguous set of pages evicted into the buffer pool extension cache.

sqlserver.buffer_pool_extension_pages_read

Page is read from the buffer pool extension cache.

sqlserver.buffer_pool_extension_pages_evicted

Page is evicted from the buffer pool extension cache.

sqlserver.buffer_pool_eviction_thresholds_recalculated

Lazywriter and/or worker clock has wrapped the BUF array and thresholds are re-calculated.

Кроме того, можно воспользоваться следующими счетчиками производительности в Performance Monitor.

  • SQLServer:Buffer Manager\Extension page writes/sec
  • SQLServer:Buffer Manager\Extension page reads/sec
  • SQLServer:Buffer Manager\Extension outstanding IO counter
  • SQLServer:Buffer Manager\Extension page evictions/sec
  • SQLServer:Buffer Manager\Extension allocated pages
  • SQLServer:Buffer Manager\Extension free pages
  • SQLServer:Buffer Manager\Extension in use as percentage
  • SQLServer:Buffer Manager\Extension page unreferenced time

 

Buffer Pool Extension в SQL Server 2014 часть 2, сравнительное тестирование производительности

Давайте посмотрим поближе, насколько можно ускорить производительность вашей системы с помощью BPE. Для тестирования я буду использовать виртуальную машину с 4 Гб оперативной памяти. Я создал отдельную базу данных с одной таблицей. В таблице всего 2 столбца [id] и [n]. Первый столбец имеет целочисленный тип данных и является первым ключом с кластеризованным индексом на нем. Второй столбец просто выполняет роль каких-то данных в системе.

use [master];
go

create database [BufferPoolExtensions_test];
go

use [BufferPoolExtensions_test];
go

create table [dbo].[TestTable] (
	[id] int identity(1,1) not null,
	[n] [char](1000) not null,
	
	constraint [PK_TestTable] primary key clustered ([id])
);
go

insert into [dbo].[TestTable] ([n])
values (replicate('A', 1000));
go 1000000

Размер таблицы получается чуть больше 1 Гб и в первом тесте она целиком будет помещаться в память. Это так называемая идеальная ситуация, когда памяти хватает для всех оперативных данных.

Тестирование будет заключаться в том, что я буду выполнять 10000 случайных запросов на выборку одной строки данных. Это хороший пример OLTP нагрузки на чтение. Данный запрос я буду выполнять несколько раз и считать среднее арифметическое результатов:

select [n]
from [dbo].[TestTable]
where [id] = cast(rand(checksum(newid())) * 1000000 as int) + 1;
go 10000

Итак, результаты первого теста, когда все данные в оперативной памяти и BPE отключен: 1.4 секунды. Это так называемая идеальная ситуация, когда памяти достаточно и все данные находятся в кэше.

Во втором результате я слегка модифицирую запрос и добавлю в него команду очистки Buffer Pool, чтобы посмотреть на «худший» вариант, когда в кэше нет никаких данных.

dbcc dropcleanbuffers;
go

select [n]
from [dbo].[TestTable]
where [id] = cast(rand(checksum(newid())) * 1000000 as int) + 1;
go 10000

Результат 2 минуты и 2 секунды.

Во третьем тесте я ограничу размер максимально доступной памяти для SQL Server до 256 Мб – это почти в 4 раза меньше, чем размер данных и попробую повторить тест. При этом стоит отметить, что во время теста в кэше не находилось больше чем 90 Мб от всех данных в таблице, что составляет примерно только 8% от всего объема. Результат: 1 минута 56 секунд. Получилось вполне ожидаемо.

В четвертом тесте я включу Buffer Pool Extension размером 4 Гб и сделаю полное сканирование таблицы перед началом теста, чтобы все данные были либо в памяти, либо в BPE. Стоит отметить, что практически все данные размещаются в BPE, т.е. SQL Server старается поместить все чистые страницы туда и не держать их в памяти. Результат теста: 4.6 секунды. Это в 3 раза хуже, чем если бы данные находились в памяти, но в 25 раз лучше, чем случайно считывать их с диска, если памяти не хватает. Вполне достойно на мой взгляд.

И последний, пятый тест. Всю базу данных я размещу на SSD диске, отключу BPE и буду очищать кэш каждый раз перед запуском. Результат: 6.3 секунды – даже медленнее, чем использовать BPE.

Итоговая таблица с результатами:

№ теста

Описание теста

Результат, время

1

Все данные находятся в памяти.

1.5 сек.

2

Все данные находятся на диске, (“холодный” кэш, в памяти данных нет).

2 мин. 02 сек.

3

Размер оперативной памяти ограничен. В кэше находится примерно 8% от всего объема данных.

1 мин. 56 сек.

4

Размер оперативной памяти ограничен как в тесте №3, но включен BPE – практически все данные находятся в BPE, а не в памяти.

4.6 сек.

5

База данных расположена на SSD, (“холодный” кэш, в памяти данных нет).

6.3 сек.

 

Итак, какой вывод можно сделать из тестирования. Использование BPE может заметно ускорить случайную выборку данных из таблицы, если памяти недостаточно для полного кэширования таблицы. При этом очень интересны результаты четвертого и пятого тестов – получается, что использовать BPE может быть выгоднее, чем располагать базу на SSD. Но опять же, стоит оговориться, что мое тестирование не отражает вашей ситуации и данные могут заметно различаться. Поэтому перед внедрением стоит протестировать опцию на вашей конкретной нагрузке и только после этого принимать решение. Если вы тоже тестировали BPE и у вас получаются другие результаты – предлагаю поделиться и обсудить это в комментариях к заметке.

В следующей статье я расскажу о способах мониторинга систем с включенным Buffer Pool Extension.

Buffer Pool Extension в SQL Server 2014 часть 1, обзор

Наверное, многие слышали фразу «640K ought to be enough for anybody», которую ошибочно предписывают Биллу Гейтсу. И хотя оперативная память постоянно дешевеет, но для сервера баз данных ее практически никогда не бывает достаточно. SQL Server обладает хорошей интеллектуальной системой кэширования часто используемых данных, но их размер почти всегда превышает размер доступной оперативной памяти, которую иногда бывает проблематично расширить. Одной из интересных особенностей, которые появятся в SQL Server 2014, является Buffer Pool Extension, которая позволяет в случае ограниченного набора памяти кэшировать страницы с данными на SSD диске. В этой статье я постараюсь сделать детальный обзор этой технологии на примере SQL Server 2014 CTP1.

Buffer Pool – область памяти (самая большая), которую SQL Server в основном использует для хранения страниц с данными. Любая страница, которая считывается с диска сначала помещается туда, а уже потом используется по назначению (для считывания или изменения данных). Страницы в памяти могут находиться в двух состояниях: так называемые «чистые» страницы, данные в которых никогда не изменялись, и «грязные», в которые были внесены изменения, но еще не сохранены обратно на диск с помощью процессов checkpoint или lazy writer. Buffer Pool Extension позволяет «увеличить» размер Buffer Pool используя для этого SSD диск. Это может быть полезно, если у вас есть возможность добавить SSD диск в ваш сервер, но нет возможности расширить оперативную память или вынести все часто используемые данные на SSD в силу каких-то ограничений. Например, можно использовать один дешевый SSD в качестве кэша в BPE не предъявляя к нему никаких требований по надежности, в то время как размещение всей или части базы данных потребует применения более дорогих и надежных систем.

Включить опцию очень легко. Для этого достаточно использовать команду ALTER SERVER CONFIGURATION и указать расположение файла и его размер, который будет использоваться в качестве Buffer Pool Extension.

alter server configuration
set buffer pool extension
on ( filename = 'X:\MyCache.bpe' , size = 64 gb );
go

После выполнения данной команды создается указанный нами файл, который сразу начинается использоваться. SQL Server может использовать его только для кэширования «чистых» страниц. Изменить расположение файла или его размер невозможно. Для этого требуется отключить BPE и включить его заново с другими параметрами. Отключается Buffer Pool Extension следующей командой.

alter server configuration
set buffer pool extension off;
go

Итак, для чего может быть полезна данная опция и какие у нее плюсы.

  1. Ее рекомендуется использовать для OLTP систем, в которых преобладают запросы на чтение данных.
  2. Нет никаких рисков потери данных, т.к. BPE кэширует только «чистые» страницы. При сбое диска BPE просто отключается.
  3. Не требуется вносить никаких изменений в приложения – все начинает работать сразу, как только вы включаете опцию.

Но, также имеются некоторые ограничения, которые требуется учитывать перед тем, как планировать использовать эту опцию.

  1. Возможность будет доступна только в редакции Enterprise Edition.
  2. Вы не можете задать файл для BPE размером меньше, чем размер текущей оперативной памяти. По крайней мере судя по моим тестам с использованием SQL Server 2014 CTP1, вы будете получать ошибку вида:

    Msg 868, Level 16, State 1, Line 18
    Buffer pool extension size must be larger than the current memory allocation threshold 2048 MB. Buffer pool extension is not enabled.

  3. Максимальный поддерживаемый размер оперативной памяти 128 Гб, т.е. обладатели систем с большим размером памяти воспользоваться опцией не смогут. И это довольно неприятный момент, т.к. такой и больший объемы вполне доступны покупателям даже для серверов начального уровня.
  4. Размер файла BPE не может превышать 32 размера вашей оперативной памяти. Т.е. максимально допустимый размер для него будет 32 x 128 Гб = 4 Тб. Рекомендуется задавать размер BPE не более 4-10 размеров оперативной памяти.
  5. Естественно располагать файл следует на быстром SSD диске, иначе смысл опции полностью теряется. И, хотя нет никаких требований к надежности, следует учесть, что если вдруг диск выйдет из строя – вы останетесь без BPE, что может существенно повлиять на производительность вашей системы, если она сильно зависит от этой опции.

Остается самый главный вопрос: насколько использование BPE может ускорить производительность системы? В следующей статье я приведу результаты тестирования BPE на нагрузке, которая будет эмулировать много случайных чтений данных – именно та нагрузка, которую BPE сможет ускорить больше всего.

Отчет о встрече Russian SQL Server UG 25.07.2013

В очередной раз в Microsoft Technology Center на Белорусской прошла встреча Russian SQL Server User Group. И, несмотря на сезон отпусков, мы собрали почти полный зал. А послушать действительно было что. Первым выступил Мартин Рахманов и рассказал про уязвимости современных БД. Приятно было услышать из уст специалиста, что SQL Server является самой защищенной платформой на сегодняшний день. Слайды и презентация были очень интересными и вызывали много уточняющих вопросов.

Вторым докладчиком был Евгений Хабаров и это был его дебют. Поздравляю Женю с отличным докладом и желаю не останавливаться и дальше продолжать делиться своими знаниями с сообществом.

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

Всем спасибо за участие. Следите за анонсами. Следующую встречу мы планируем посвятить целиком и полностью обзору нововведений SQL Server 2014.

[print_gllr id=583]

Начала работу российская виртуальная группа по SQL Server

С радостью готов сообщить, что все формальности решены и при поддержке PASS в России начала работу виртуальная группа по SQL Server. Теперь все даже в отдаленных уголках нашей большой страны смогут в режиме онлайн послушать интересные презентации, посвященные SQL Server и задать свои вопросы докладчикам. Время все встреч запомнить очень просто: каждую третью неделю месяца по средам в 15:00 по Московскому времени. 3-3-3 (третья неделя, третий день, 3 часа для).

Начинаем 21 августа. Вы услышите первую часть доклада “Индексы и все, все, все”. Докладчиком будет Дмитрий Короткевич (Microsoft SQL Server MVP, Microsoft Certified Master). Он работает с SQL Server более 11 лет, специализируясь в архитектуре, разработке и оптимизации OLTP систем. Дмитрий ответственен за внедрение нескольких решений обрабатывающих тысячи транзакций в секунду в режиме 24×7.

Ссылка на официальный сайт группы, где вы можете посмотреть список докладов и зарегистрироваться: http://russianvc.sqlpass.org/

Анонс: июльский (2013) семинар SQL Server User Group

Уважаемые коллеги, очередной семинар Russian SQL Server User Group запланирован на 25 июля 16:00-19:00 в помещении Microsoft Technology Center (переговорная «Арсенальная») по адресу Москва, ул.Лесная, 5с, проезд до станции метро Белорусская (кольцевая).

В программе семинара:

Мартин Рахманов, «Уязвимости современных баз данных на примерах»

В докладе будут продемонстрированы уязвимости текущих версий популярных СУБД: Oracle Database 11g R2, Microsoft SQL Server 2008, Sybase ASE 15.7 и IBM DB2 LUW 10.1. Демонстрации покажут каким образом непривилегированный пользователь может получить административный доступ и, таким образом, доступ ко всем данным.

Мартин Рахманов занимает должность старшего инженера-исследователя в Application Security Inc (Нью-Йорк), где он отвечает за поиск уязвимостей в СУБД и поддержку продуктов компании. До этого работал ведущим инженером-разработчиком в компании Рексофт (Россия).

Евгений Хабаров, «Конкуренция за ресурсы в многоядерных системах: LATCHи и SPINLOCKи»

В настоящее время все больше старых серверов с небольшим количеством ядер выводятся из эксплуатации и заменяются современными многоядерными системами, основанными на архитектуре NUMA. В таких системах все чаще можно наблюдать конкуренцию при доступе к различным системным объектам в связи с параллельным выполнением большого количества запросов. В докладе пойдет речь о LATCHах и SPINLOCKах, основных типах проблем, связанных с конкурентным доступом, и методах их решения.

Евгений Хабаров, разработчик баз данных в компании Яндекс. MCITP по направлению development. Работает с SQL Server, начиная с 2000-ой версии. С ростом сложности задач приходилось углубляться все больше и больше в недра SQL Server, и чем дальше, тем сложнее и интереснее. Механизмы настолько разнообразные, что изучать их можно, кажется, бесконечно.

Приглашаем вас посетить наш семинар. Участие бесплатное, но необходимо предварительно зарегистрироваться на сайте Ineta: http://ineta.ru/sqlrus/Meeting/2013-07-25-16-00 При себе необходимо будет иметь паспорт, чтобы охрана пропустила в здание бизнес центра.

Microsoft SQL Server 2014 CTP1 доступен публично

Microsoft SQL Server 2014 Community Technology Preview 1 (CTP1) стал доступен для публичного скачивания. Вы можете получить доступ к нему по следующей ссылке: http://technet.microsoft.com/en-US/evalcenter/dn205290.aspx?lc=1033

Также есть возможность ознакомиться с предварительной версией официальной документации: http://msdn.microsoft.com/en-us/library/bb418471(v=sql.10).aspx

Try SQL Server 2014 CTP1

Анонс встречи RuBI PASS Chapter: использование SQL Server Parallel Data Warehouse (PDW) и Hadoop для построения хранилищ данных (DWH)

27 июня в 19:00 в Москве пройдет очередная встреча Russian BI PASS Chapter. Состоится она как обычно в Microsoft Technology Center, м. Белорусская. Докладчик: Андрей Резник, Microsoft.

Microsoft SQL Server Parallel Data Warehouse (PDW) – это высокопроизводительная платформа для организации аналитического хранилища данных (DWH) от десятка до сотен ТБ, обеспечивающая отличную производительность и масштабируемость.Parallel Data Warehouse использует архитектуру обработки больших объемов данных, состоящую в распределении данных и параллельной обработки на разных серверах (узлах). Каждый из узлов использует свои собственные процессоры, память и дисковые ресурсы. Такой подход называется обработкой с массовым параллелизмом (MPP).

Мы рассмотрим базовые принципы, заложенные в PDW, его архитектуру, состав серверов, рекомендации к проектированию схемы данных. Также взглянем на Hadoop, экосистему для построения распределенных систем, и его интеграцию с PDW.

Встреча пройдет в максимально интерактивном режиме. Мы планируем не просто рассказ об указанных технологиях, но и организовать круглый стол и обсудить вопросы построения хранилищ. У вас есть уникальная возможность пообщаться с коллегами и одним из ведущих экспертов в данной области.

Вход бесплатный, но требуется предварительная регистрация по следующей ссылке: http://ineta.ru/rubi/Meeting/2013-06-27-19-00. При себе необходимо будет иметь паспорт, чтобы пройти в бизнес центр. До встречи! 🙂

Генерация скриптов для создания и удаления объектов SQL Server и с помощью Powershell

В свой предыдущей статье я показал, как можно использовать мастер SQL Server Management Studio для генерации скриптов для различных объектов SQL Server. Мастер обладает большим набором возможностей, но также и рядом недостатков. Например, мы видели, что нельзя легко сгенерировать скрипты для всех объектов из определенной схемы, кроме как вручную указать все эти объекты. В этой статье мы рассмотрим другой подход к генерации скриптов – программный. Для этого мы будем использовать Powershell, мощное и гибкое средство для управления любыми Windows машинами или сервисами, в том числе и SQL Server.

Самый простой способ – запустить Powershell прямо из SSMS.

У вас откроется консоль Powershell, в которой уже будет загружен модуль SQLPS и открыт путь до нашей базы данных. Здесь можно просматривать и работать с объектами также, как и с файлами и папками. Например, с помощью следующего набора команд мы перейдем к таблицам в нашей базе данных, получим список всех таблиц в переменную и для первой таблицы в списке сгенерируем скрипт.

# Переходим к списку таблиц
cd Tables

# Считываем все таблицы в массив
$tables = Get-ChildItem

# Выводим информацию о первом элементе
$tables[1]

# Для первой таблицы генерируем скрипт
$tables[1].Script() 

У вас должно получиться что-то подобное, как на скриншоте снизу.

Но, если мы хотим, например, сгенерировать не скрипт создания, а скрипт удаления указанной таблицы. Для этого потребуется создать объект класса Microsoft.SqlServer.Management.Smo.ScriptingOptions, указать у него определенные свойства (а их у объекта большое множество) и снова вызвать метод Script у таблицы, в который в качестве параметра передать объект со свойствами.

# Создаем новый объект класса Microsoft.SqlServer.Management.Smo.ScriptingOptions
$script_options = New-Object ('Microsoft.SqlServer.Management.Smo.ScriptingOptions')

# У этого объекта выставляем свойство ScriptDrops в значение true
$script_options.ScriptDrops = $true

# Снова запускаем метод Script с указанными опциями
$tables[1].Script($script_options) 

Мы даже можем указать имя файла и сохранить сгенерированный скрипт в файле.

# Указываем файл, куда будет сохранен скрипт
$file_name = "C:\Temp\MyScript.sql"

# Перенаправляем вывод с консоли в указанный файл
$tables[1].Script($script_options) > $file_name 

Или используя цикл, обойти все объекты по определенному условию и сохранить скрипты в нужном месте.

# Для всех таблиц, имя которых начинается на Pro, сгенерировать скрипты с опциями, указанными в $script_oprions и выложить скрипт для каждого для каждого отдельного объекта в папку C:\Temp в формате <Имя схемы>.<Имя таблицы>.sql
foreach ($t in $tables | Where-Object { $_.Name.StartsWith("Pro") }) { $t.Script($script_options) > "C:\Temp\$($t.Schema).$($t.Name).sql" } 

Как мы видим, набор возможностей практически не ограничен за одним исключением. Набивать эти команды в консоли крайне неудобно. Гораздо удобнее написать отдельный скрипт и вызывать его по мере необходимости. Хочу привести пример отдельного скрипта на Powershell для генерации скриптов создания всех таблиц в базе с ограничениями, внешними ключами и т.п. в один большой скрипт с разделителями.

# Загружаем модуль для работы с SMO объектами.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null

# Объявляем переменные и указываем имя сервера, имя базы данных и путь до файла, куда будет сохранен скрипт создания всех таблиц.
$srv_name = "(local)"
$db_name = "AdventureWorks2012"
$file_name = "C:\Temp\CreateAllTables.sql"

# Объявляем объект класса Microsoft.SqlServer.Management.Smo.Server.
$srv = New-Object('Microsoft.SqlServer.Management.Smo.Server') $srv_name

# Получаем объект нужной нам базы данных.
$db = $srv.Databases[$db_name]

# Создаем объект класса Microsoft.SqlServer.Management.Smo.Scripter, который будет выполнять всю работу по созданию скриптов.
$scripter = New-Object('Microsoft.SqlServer.Management.Smo.Scripter') $srv

# Указываем, что в скрипт нужно включать все DRI объекты (Declarative Referential Integrity: ограничения, внешние ключи и т.п.).
$scripter.Options.DriAll = $true
# Включать в скрипт создание индексов.
$scripter.Options.Indexes = $true
# Включать в скрипт добавление расширенных свойств.
$scripter.Options.ExtendedProperties = $true

# Указывать в скрипте разделитель GO между командами создания объектов.
$scripter.Options.ScriptBatchTerminator = $true
$scripter.Options.NoCommandTerminator = $false

# Указываем, что сохранять скрипт необходимо в файл.
$scripter.Options.FileName = $file_name
$scripter.Options.ToFileOnly = $true
$scripter.Options.AppendToFile=$true

# Для всех таблиц, имя которых начинается на Pro, сгенерировать скрипты и добавить их в указанный файл.
foreach ( $t in $db.Tables | Where-Object { $_.Name.StartsWith("Pro") } ) {
    $scripter.Script($t)
}

На этом все. Я постарался привести максимально полезные примеры, от которых вы сможете отталкиваться при написании своих скриптов на Powershell.