|
Программирование >> Программирование баз данных
говоря, это утверждение не совсем справедливо, поскольку сам по себе оператор SELECT не позволяет непосредственно осуществлять печать с помощью оператора PRINT, но на его основе может быть создана практически аналогичная программная структура). Тем не менее этот код обладает важной отличительной особенностью, поскольку позволяет применять практически любые операции к отдельным строкам. Перейдем к практическим действиям и покажем такую возможность, дополнив рассматриваемый фрагмент кода. Предварительно следует отметить, что в предьщущих выпусках SQL Server не был предусмотрен какой-либо отдельно взятый оператор, который позволял бы перестроить все индексы во всей базе данных (к счастью, в современном выпуске предусмотрена опция в команде DBCC INDEXDEFRAG, которая позволяет распространить действие этой команды на всю базу данных). Однако поддержка индексов в дефраг-ментированном состоянии относится к одной из наиболее важных задач администрирования системы. Рассмотрим пример курсора, предназначенного для решения этой задачи, в основе которого лежит некоторая разновидность общепринятого способа дефрагментации индексов. Но в этой новой версии используется конкретная информация о фрагментации и обеспечивается возможность выполнять дефрагмен-тацию с помощью оператора ALTER INDEX (который позволяет точнее всего указать, как должна осуществляться дефрагментация), а не команды DBCC INDEXDEFRAG. Отметим, что имеется несколько различных способов, позволяющих перестраивать или реорганизовывать индексы, не удаляя и не воссоздавая их полностью. При этом способ, основанный на использовании оператора ALTER INDEX, является наиболее гибким, поскольку позволяет выбирать различные основополагающие методы дефрагментации (в оперативном или автономном режиме, с полной перестройкой индекса или с реорганизацией только определенной его части и т.д.), поэтому попытаемся решить поставленную задачу именно с его помощью. Простая версия синтаксиса оператора ALTER INDEX выглядит следующим образом: ALTER INDEX <index name> ALL ON <object> {[REBUILD] I [REORGANIZE]} Еще раз отметим, что это- предельно упрощенная версия оператора ALTER INDEX. Фактически этот оператор может применяться в сочетании с другими многочисленными параметрами и опциями, которые рассматривались в главе 8. Предпринимая попытку использовать оператор ALTER INDEX для перестройки всех индексов во всех таблицах, необходимо учитывать, что этот оператор предназначен для обработки только одной таблицы одновременно. Безусловно, чтобы осуществить перестройку всех индексов таблицы, можно задать вместо имени индекса опцию ALL, но возможность оставить незаданным имя таблицы, для перестройки всех индексов всех таблиц, не предусмотрена. Даже при использовании такого инструментального средства, как DBCC INDEXDEFRAG, действие которого может распространяться на всю базу данных, не предусмотрен широкий выбор вариантов возможных действий, поскольку любая команда (или оператор), применяемая без дополнительного управляющего кода, не позволяет применять определенные действия к отдельным объектам выборочно. Иными словами, проводя обработку, мы не имеем возможности непосредственно указать, что должна быть, например, проведена реорганизация только тех индексов, фрагментация которых превысила определенный уровень, или исключить конкретные таблицы, в которых желательно иметь некоторую фрагментацию. Следует учитывать, что при определенных обстоятельствах фрагментация может оказаться полезной. В частности, фрагментация становится благоприятной в таких условиях использования таблиц, в которых выполняется большое количество операций вставки в произвольно выбранных позициях, поскольку приводит к сокращению количества случаев разбиения страниц. С помощью курсора появляется возможность решить эту проблему исключительно путем динамического формирования команды DBCC: DECLARE ©SchemaName varchar(255) DECLARE ©TableName varchar(255) DECLARE ©IndexName varchar(255) DECLARE ©Fragmentation float DECLARE ©Command varchar(255) DECLARE TableCursor CURSOR FOR SELECT SCHEMA NAME{CAST{OBJECTPROPERTYEX{i.object id, Schemald) AS int)), OBJECT NAME{i.obj ect id) , i.name, ps. avg f ragmentation in j)ercent FROM sys.dm db index j)hysical stats {DB ID{), NULL, NULL, NULL, NULL) AS ps JOIN sys.indexes AS i ON ps.object id = i.object id AND ps.index id = i.index id WHERE avg fragmentation in percent > 3 0 OPEN TableCursor FETCH NEXT FROM TableCursor INTO ©SchemaName, ©TableName, ©IndexName, ©Fragmentation WHILE ©©FETCH STATUS = 0 BEGIN PRINT Reindexing + ISNULL{©SchemaName, dbo) + . + ©TableName + . + ©IndexName SET ©Command = ALTER INDEX [ + ©IndexName + ] ON [ + ISNULL{©SchemaName, dbo) + + ©TableName + ] REBUILD EXEC {©Command) FETCH NEXT FROM TableCursor INTO ©SchemaName, ©TableName, ©IndexName, ©Fragmentation CLOSE TableCursor DEALLOCATE TableCursor Итак, применение курсора позволило решить задачу, выполнение которой было бы невозможно при использовании только операторов, действующих на уровне множества. Команда ALTER INDEX принимает единственный параметр, в связи с тем, что набор записей не может применяться. Но мы смогли устранить эту проблему путем совместного применения операции с множеством (операции с конструкцией SELECT, который формирует основу для курсора) и операций построчной обработки данных (операций курсора). Но для получения возможности включения в единый сценарий и операции с множествами, и операций построчной обработки данных нам пришлось выполнить целый ряд шагов. Вначале был объявлен курсор и все необходимые промежуточные переменные. После этого курсор был открыт, и только с этого момента фактически появилась возможность выборки данных из базы данных. Затем мы приступили к использованию курсора, проходя по представленному в нем набору строк. В данном случае прохождение по набору строк курсора осуществлялось только в прямом направлении, но, как будет описано ниже, может быть создан курсор, позволяющий выполнять прокрутку вперед и назад. На следующем этапе работы курсор был закрыт (если ко времени закрытия в курсоре еще имеются какие-либо открытые блокировки. то после этого они освобождаются), но память для курсора оставалась распределенной. Наконец, мы освободили курсор. С этого времени все ресурсы, используемые курсором, освобождаются и становятся доступными для применения другими объектами в системе. Таким образом, приведенный выше краткий пример наглядно демонстрирует многие нюансы работы с курсорами. Но фактически это только начало. Курсоры предоставляют гораздо большие возможности по сравнению с тем, что можно было показать в данном конкретном примере. Поэтому продолжим изучение данной темы и рассмотрим более подробно некоторые мощные функции, благодаря которым курсоры приобретают дополнительные возможности. Типы курсоров и расширенный синтаксис объявления Курсоры подразделяются на несколько разных типов (в настоящей главе будут кратко описаны все эти типы). По умолчанию курсор является последовательным, FORWARD ONLY (это означает, что с его помощью можно передвигаться в наборе строк только вперед, но не назад), и предназначен только для чтения, но курсоры могут быть также прокручиваемыми и обновляемыми. Кроме того, курсоры могут быть в разной степени восприимчивыми к изменениям, которые вносятся в основополагающие данные другими процессами. Последовательные курсоры, предназначенные только для чтения, представляют собой применяемый по умолчанию тип курсора не только в собственной машине обработки курсоров СУБД SQL Server, но и во многих других моделях поддержки курсоров, с которыми когда-либо приходится сталкиваться. В сравнении с курсорами других типов последовательные курсоры, предназначенные только для чтения, характеризуются чрезвычайно нижими издержками, поэтому их часто называют пожарными иыангами (firehose), в связи с тем, что они пропускают через себя данные в одну сторону с огромной скоростью. Как и пожарный шланг, firehose-курсор направляет через себя содержимое только в одном направлении (аналогия с пожарным иллангом состоит еще и в том, что вылитую воду также нельзя вернуть по нему назад). В большинстве случаев firehose-курсоры превосходят по своему быстродействию все другие разновидности курсоров, но из этого не следует, что достигаемая производительность выше по сравнению с реляционными операциями; курсоры всегда работают медленнее, чем большинство эквивалентных операций с наборами строк, и исключение не составляют даже firehose-курсоры. Начнем с рассмотрения более расширенного варианта синтаксиса объявления курсора, а затем отдельно приведем описание всех параметров этого объявления: DECLARE <cursor name> CURSOR [LOCAL I GLOBAL] [FORWARD ONLYSCROLL] [STATIC I KEYSETDYNAMICFAST FORWARD] [READ ONLYSCROLL LOCKSOPTIMISTIC] [TYPE WARNING] FOR <SELECT statement> [FOR UPDATE [OF <column name >[,...n]]] Ha первый взгляд создается впечатление, что синтаксис объявления является очень сложным, и действительно, при создании курсоров приходится учитывать много нюансов (но, как уже было сказано, при этом наиболее важное требование состоит
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |