Разделы
Публикации
Популярные
Новые
Главная » Оптимизация производительности transact

1 ... 5 6 7 8 9 10 11 ... 55

CASb stdt,us2 S 1048576 ni-LK G Г|Е ti.SE .ceiu]z to ioca: сьгзог

CASE statJ52 i 8388608 WHEN 0 THEN ELSE .quoted -.dentifier END+ CASE 5tatus2 & 33554432 WHEN 0 THEN ELSE .Cjrsor close on corTimit\ END+

CASE status2 & 67108864 WHEN 0 fHEN ELSE .ANSI NLLLs END* CASE status2 & 268435456 WHEN С THEN ELSE .ANSI warnings END+ CASE status2 & 536870912 WHEN 0 THEN ElSE .full text enabled END. 2.8000) AS Descmptlon FROM masten,.sysdatabases

DB Description

CM select into/bulk copy,torn page detecticn.autosnnnK

masten trunc. log on chkpt

model select into/bulk copy.trunc. leg on chkpt,tonn page

detection,autoshrlnk msdb select into/buk copy,trunc. log on chkpt .autoshrink,

cleanly shutdown

Northwmd select into/bulk copy.trunc. log on cnkpt.autoshrlnk .cieaniy shutGown

Northwind2 autoclose,select Into/buk coDy,trunc. log on chkpt.torn page

detect ion,autoshrink,с lean! PM autoclose,select Into/bulk copy.tnunc. log on

chkpt.autoshrlnk.cleanly shutdown PC autoclose.select into/bulk copy.tnunc, log on

chkpt,autoshrink,cleanly snutdown pubs select into/buk coDy,tnunc, log on chkpt,auioshnnk

SCW TS autoclose,select into/bulk copy,tnunc, log on chkpt,tonn page

detection,autoshrink tempdb select into/bulk copy.tnunc, log on chkpt,ANSI NULL deault

Здесь мы использовали запрос к таблице sysdatabases в базе данных master, чтобы раскодировать два статусных столбца (status и status2) для каждой базы даины.х. Числа, указанные в каждо.м выражении CASE, - это битовые маски; столбцы статуса - последовательности битов, Каждь[й флаг статуса, который может быть у базы данных, представлен бито.\г или бнта.ми в одно.м из двух этих столбцов. Мы используем поразрядны!! оператор &, чтобы naiiTn соответствие значений сто-тбца статуса значениям иереюночателей, соответствующих каждому флагу,

ПРИМЕЧАНИЕ--

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

Са.м SQL Server интенсивно использует битовь!е последовательности и бито-вь!е маски, пото.\!у что oni! представляют собой эффе!Ш1Вный способ хранения сгатус!1ых флагамов i! управления и.ми. Например, таблица sysindexes содержит столбец с назван![е.м statblob, которь!Й служит для управления статистикой индексов. Это стсмбец типа image, который !ia самом деле не хранит изображение - он хранит бхттовую последовательность, представляющую информацию о распределени!! ючюча индекса.



UNIQUEIDENTIFIER

Тип данных uniqueidentifer применяется для хранения GUID (глобапьных уникальных идентификаторов). GUID - это 16-байтовое двоичное число, для которого гарантируется уникатьность среди всех компьютеров в ,мнре. СОМ-интерфейсы Windows используют GUID для своей идентификации. Так как они унггкальны на всех компьютерах в мире, они предоставляют универсальную схе.му ну.мерации СОМ-интерфейсов. Функция Transact-SQL NEWID() служит для генерации новых GUID. Она может при.меняться в качестве значения столбца по у\юлча-нию, как здесь: SET NOCOUNT ON

CREATE TABLE #guid£ (cl uniqueidentif1er DEFAULT NEWIDO)

INSERT #guids DEFAULT VALUES

INSERT #guids DEFAULT VALUES

INSERT #guids DEFAULT VALUES

INSERT #guids DEFAULT VALUES

SELECT * FROM #guids

DROP TABLE #guids cl

07A7DEFF-367F-11D3-92AC-005004044A19 07A7DF00-367F-11D3-92AC-005004044A19 07A7DF01-367F-11D3-92AC-005004044A19 07A7DF02-367F-11D3-92AC-005004044A19

Каждая таблица может иметь произвольное количество столбцов типа uniqueidentifler, один столбец может и.меть идентификатор ROWGUIDCOL. Свойство ROWGUIDCOL люжет быть использовано для косвенного доступа к соответствующему столбцу uniqueidentifler без явного указания его и.меии (аналогично IDENirrYCOL). Вот пример:

SET NOCOUNT ON

CREATE TABLE #guids (cl uniqueidentifler DEFAULT NEWIDO ROWGUIDCOL)

INSERT #guids DEFAULT VALUES

INSERT #guids DEFAULT VALUES

INSERT #guids DEFAULT VALUES

INSERT #guids DEFAULT VALUES

SELECT ROWGUIDCOL FROM #guids

DROP TABLE #gu1ds cl

07A7DF1D-367F-11D3-92AC-005004044A19 07A7DF1E-367F-11D3-92AC-005004044A19 07A7DF1F-367F-11D3-92AC-005004044A19 07A7DF20-367F-11D3-92AC-005004044A19

Тип uniqueidentifler имеет множество недостатков. Вот некоторые из них:

О Их значения громоздкие и загадочные. Они случайны и не соответствуют мнемоническому образцу.



О Тип uniqueidentifier в четыре раза бо.п^ше типа int, который обычно используется в качестве идептификатора записей. Это замедляет доступ к ним, включая создание и доступ к индексам, построенным по иим.

О По сами.\г значениям нельзя определить последовательность, в которой лгно-жество значений uniqueidentifier было сгенерировано - вы ие сможете сказать, какое значение первое, а какое - следующее, взглянув на данные. Кро.ме этого, это означает, что они плохо подходят для столбцов в ORDER BY.

Переменные курсорного типа

Пере.\гениые курсорного типа хранят ссылку на определение курсора. Курсоры, ооъявлепнь[е с по.мощью переменных - это по определению локальные курсоры (так как нельзя объявлять глобатьные переменные), и они могут быть использованы вместо прямых ссылок на курсоры в таких ко.мандах, как OPEN, FETCH, CLOSE и DEALLOCATE.

Они поддерживают !юлнь[й синтаксис Transact-SQL для работы с курсорами и .vforyr при.меняться для объявления как курсоров только для чтения, так и обновляемых курсоров. Курсорные переменные и курсорный тип данных могут быть использованы в больщиистве случаев, где можно применять обычные переменные и типы данных, однако есть три исключения:

О нельзя создать столбец таблиць[ курсорного типа;

О нельзя объявлять входные параметры храни.мых процедур как курсоры (но можно объявлять выходные пара.метры курсорного типа);

О нельзя npncBatHiaTb значения курсорной переменной с помощью оператора SELECT. (Значения и.м должны присваиваться с по.мощью ко.манды SET command.)

Вот при.мер объявления простой курсорной переменной:

DECLARE @cursor CURSOR

SET (acjrsor=CURSOR FOR SELECT * FROM autnors OPEN @cursor FETCH (Bcursor

WHILE {(a(aFETCH STATUS=0) BEGIN FETCH gcursor

CLOSE ecursor DEALLOCATE @cursor

В этом примере мы объявляем курсор, используя оператор присваивания SET. Курсорным переменным также можно присваивать существующие курсоры, как здесь:

DECLARE gcursor CURSOR

DECLARE с CURSOR FOR SELECT * FRCM authors

SET gcursorc

OPEN Ocursor

FETCH (?cursor

WHILE {(a(aFETCH STATUS-0) BEGIN FETCH ecursor



CLOSE (PCbrsor DEALLOCATE gcursor DEALLOCATE с

Здесь мы сначала объявляем курсор с пр[[мененнем традиционного синтаксиса DECLARE CURSOR; затем присваиваем значение, используя название курсор-Hoii переменной. Обратите внимание на отдельное освобождение курсорной не-ре.менной и курсора. Освобождения только курсора недостаточно; он остается в па.мяти до тех пор, пока явно не освобожден или пока последняя переменная, ссылающаяся на него, не выйдет из области видимости независимо от того, какая из них будет последней. Например, рассмотрим такой вариант кода:

DECLARE ©cursor CURSOR

DECLARE с CURSOR FOR SELECT * FROM authors

SET (acursor=c

DEALLOCATE с

OPEN (Pcursor

FETCH gcursor WHILE ((a(aFETCH STATUS-0) BEGIN FETCH (Pcursor END

CLOSE (acursor DEALLOCATE Ocursor

После того как вы присвоили обычный курсор курсорной неременной, вы можете ссылаться на этот курсор, используя его обычное и.мя или переменную - они почти синони.мы. Как только вы открыли курсор с помощью курсорной пе-ре.менной, как в последнем примере, вы не сможете открыть его снова, применяя обычное имя курсора, не закрыв его сначала, - он уже открыт. Аналогично, закрытие курсорной переменной закрывает оригинальный курсор - они ссылаются на одну ту же внутреннюю структуру. Как правило, они взаимозаменяе.мы. Единственное исключение - команда DEALLOCATE.

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

Вы можете объявить больше одной нере.менной, ссылающейся на конкретный курсор, и присвоить одну курсорную переменную другой. Вот пример:

DECLARE ©cursorl CURSOR. iacursor2 CURSOR

DECLARE с CURSOR FOR SELECT * FROM authors

SET Ocursorl=c

SET @cursor2=@cursorl

OPEN (acursor2

FETCH (acursor2 WHILE {(a(aFETCH STATUS=0) BEGIN FETCH (acursorl END

CLOSE (Pcursorl DEALLOCATE gcursorl



DEAL LOCATE С

Есть одно удобстпо, связанное с KypcopiHii.NHi переменнь[\ш в Transact-SQL, - поддержка выходных параметров курсорного типа. В прошлом возврат курсора из храни.мой процедуры оз1гачал либо его немедленное отображение, либо иоме-щение его содержи.мого в таблицу с noNwmbio INSERT... EXEC. Курсорные переменные дают больше контроля над те.\г, когда н как отображать результирующее .множество хранимой процедуры. Вы .можете вызвать FETCH, чтобы вернуть ре-зультирую1цее .множество по одной записи или чтобы по.местить их в переменную, а можно просто закрыть н освободить курсор, -~ ва.м решать.

Несколько систе\н1ых храпи.\н.1х процеду]), связан!п)1х с курсора.ми, возвращают выходные параметры курсорного типа. Sp describe cursor, например, возвращает курсор, который указывает на результирующее .множество, состоящее из одной записи, с онисание.м указанного вамп курсора. Для этого требуется определить курсорную переменную н передать ее процедуре в качестве OUTPUT-параметра, как здесь:

DECLARE Cacursor CURSOR

DECLARE с CURSOR GLOBAI FOR SELECT * EROM auttiors OPEN с

EXEC sp descnbe CL.rsor ( cursor return-!pcurs.or OUiPUl,

(acursor source-Nglobal.

(acursor 1dentity=Nc

FETCH (Pcursor FETCH с

WHILE ((agFETCHJTATdS-O) BEGIN

FETCH с

CLOSE (acursor CLOSE с

DEALLOCATE Cursor DEALLOCATE с

(результаты сокращены)

reference narr,e cursor naine cursor scope siatus node concurrency

с с 2 13 3

scrollable open status cursor rows

0 1 -1

После того как эта процедура обработает курсор, код закроет и освободит курсор, так же как и его собственный глобальный курсор. В это.м случае достаточно одного вызова FETCH для получения единственной записи sp describe cursor. Если курсор, который вернула хранимая процедура, содержит результирующее множество из нескольких записей, необходимо будет обработать их в цикле, выбирая каждую запись отдельно. Проиллюстрируе.м следующий вызов к sp cursor list:

DECLARE laauthorcursor CURSOR. (pautho,-cursor2 CURSOR. Pcursorlist CURSOR DECLARE AuthorsList CURSOR GLOBAL FOR SELECT * FROM authors SET (aauthorcursor=AuthorsList SET (aauthorcursor2=AuthorsList



OPEN A.:hO-bL4T,

EXEC sp C,.sor lis: @Cu-so return=?curSGrl ;st OUiU @cursor 5Cope=3

FEICH gcjrsoriist WHILE Oe-fETCHjlATUSG; BEGIN FETCH (Sd-rSCliSt l\D

ClCSE Scursorost CLOSE AutriCrsList DEALLOCATE ?CJr50rlist DEALLOCATE AuthorsList DEALLOCATE gautnorcursor DEALLOCATE PaunorcursorZ

(результаты сокращены)

reference пате cursor name

cursor 5cope siatus model @cursoriiSt MICR0S0FT SSJ5324227<8 1 -13

concurrency scrollable 1 1

reference rame cur5or nane cursor scope status model

@authorCLirsor2 AuthorsList 1 1 3

concurrency scrollable

reerence name cjrsor name

cursor scope status mocel concurrency scrollaole

Sauthorcursor AuthorsList refererce naiiie cursor name AuthorsList AuthorsList

1 13 3 0 cursor scope status mode concurrency scrollable

2 1 3 3 0

Sp cursorJist предоставляет основную информацию, как и sp describe cursor, но показывает инфор.магцш более чем об одном курсоре (обо всех глобальных, локальных U других типах курсоров). Курсор, который она возвращает в @cursorlist, выбирается по одной записи, пока не будет полностью просмотрен; затем курсор закрывается и освобождается, как и раньше.

Обратите внн.мание, что невоз.можность использования курсоров в качестве входных !1ара.метров означает, что курсорный выходной параметр процедуры может не иметь выделенного курсора до передачи его в процедуру. Если бы в SQL Server это было разрешено, можно было бы обходить ограничения для входных параметров, так как выходной пара.метр разрешено рассматривать и использовать, как любой другой параметр процедуры. Вот пример:

-- Не дела11те так

-- Плохой Transact-SQL

USE pubs

IF (0BJECT ID;1nputcursorparm) IS NOT NULL)



Тип timestamp

Несмотря на свое название, столбцы типа timestamp не н.меют никакого othohic-ния к времени или дате. Timestamp - это специальное значение тппа binary(8), для которого гарантирована уникальность для всей базы данных. Столбец тина timestamp изменяется каждый раз, когда меняются данные в заппси. В юности SQL Server столбцы тина timestamp исиользовались для создания простой стратегии опти.мистических блокировок, которую лучп1е объяснить па примере. Если Джульетта из.меняет запись после того, как Ромео считал ее, ио до того, как он записал свои из.мепепия, попытка Ромео обновить запись будет неудачной, потому что для нахождения обгювляе\ю11 заниси будет при.меняться первоначальное значение timestamp. Оператор UPDATE Ромео будет включать столбец timestamp в нредложеиие WHERE, но найти первоначальную запись е.му пе удастся, так как зпачепие ее timestamp изменилось из-за модификации, совершенной Джульеттой. Из-за этого Ромео не сможет перезаписать изменепня, внесенные Джульеттой, и он сможет обнаружить тот факт, что другой пользователь из.менил запись, которую редактировал Ро.мео.

Для сравнения значений типа timestamp можно при.менить функцию TSEQUAL(). Если значения различны, TSEQUAL() вызывает ошибку и прерывает текущий пакет команд.

Таблица может иметь только один столбец типа timestamp. Обычно этот столбец так и называют - timestamp, но это не требуется сервером. Вот при.мер кода, который показывает, как использовать тин данных timestamp:

SET NOCOUNT ON

CREATE TABLE ftestts (cl int identity. c2 int DEFAULT 0. changelog timestamp)

INSERT ftestts DEFAULT VALUES INSERT ftestts DEFAULT VALUES INSERT ftestts DEFAULT VALUES

ЖР PICC irputcursorpariT;

CREATL PSOC inputcursorparip {Scursor ipput cursc VARYING OUT AS

FECH ?curSor input WHILE (ipFETCHJTAlUS-O) BEGIN FECli ?curSor input

CLOSE ( carSOr input DEALLOCATE facurscinput GO

DECLARE &c CURSOR

SE gc=CURSOR FOR SELECI FROM autnors

-- При вь:Зозе этой процедурь, будет сгеиерироьа.1а сшибка, гак как

-- @с ccbLiaeTCfl иа существующий курсор

EXEC inputcursorparn tc OUT

Server: Msg 16951. Level 16. State 1. Line 7

The variable (?c cannot be used as a parameter because a CURSOR OUTPUT parameter must not have a cursor allocatec to it before execution o the procecure.



INSERT Itestts DEFAULT VAlULS INSERT #testts DEFAULT VALUES SELECT * FROM #testts UPDATE #testts SET c2=cl SELECT * FROM #testts

DROP TABLE #testts

change iog

1 2 3 4 5

0 0 0 0 0

0x0000G0000G0CC085 0x0000C000CC000C86 0x0000000000000087 0x0000000000000088 0x0000000000000089

changelog

OxOOOOOOOOOOOOOOBA 0x000000000000008В 0x0000000000000080 0x0000000000000080 OxOOOOOOOOOOOOOOBE

Обратите внимание на разные значения для каждого столбца timestamp запис! до и после UPDATE. Вы можете получить последнее сгенерированное для базь данных значение timestamp с по.мощыо автоматической переменной @@DBTS У каждой базы данных есть свой счетчик, поэтому убедитесь, что вы находитео в нужной базе данных, прежде че.м получать значение @@DBTS. Вот пример:

USE tempdb GO

SET NOCOUNT ON

CREATE TABLE #testts (cl int identity. c2 int DEFAULT 0. changelog timestamp) INSERT #testts DEFAULT VALUES INSERT #testts DEFAULT VALUES INSERT ftestts DEFAULT VALUES INSERT ftestts DEFAULT VALUES INSERT #testts DEFAULT VALUES SELECT * FROM ftestts SELECT mBlS AS Last timestamp UPDATE ftestts SET c2=cl SELECT * FROM ftestts SELECT (a(aOBTS AS Last timestamp GO

DROP TABLE ftestts

changelog

0x0000000000000087 0x0000000000000088 0x0000000000000089 OxOOOOOOOOOOOOOOBA OxOOOOOOOOOOOOOOBB



LaSl r.iineslomp

ОхООООООООООООООВВ cl c2

cr.ac.ue oc

OxCCOCOGOOGCCOOGdC OxOeCOCOCGGGOOCCBD OxOGOOOCGGCOGOOOBE ОхООООООООССОСООВГ OxCOCCGGOOOOCOOOCC

Last, timestamp OxCOOOOOOOOOOGOOCC

Обратите вни,мание иа KONiauiiy USE в иачаче сценария. Так как времеииые таблицы располагаются в tempdb, для правильной работы @@DBTS необходимо изменить текущую базу данных на tempdb,

@@DBTS всегда возвращаег последнее значение timestamp, сгенерированное для базы данных, так что вы можете применить ее для получения зиачеиия timestamp для последней совершенной ва\и1 моди(1)ика1И1и, подобно авто,матнческо11 пере-мешой @@IDENTrTY, Единственная бо;ц.ша>1 р;1зница между @@DBTS и @@IDENTrrY состоит в том, что @@IDENTnY сиеци(})ична для соединения, @@DBTS - для базы данных. Значения, полученные с по.мощью @@IDENTITY, редко будут одинако-вы.мп для нескольких пользователе]!, тогда как значение @@DBTS часто будет одинаково для всех пользователей, иодкл10ч<.чн1ых к данной базе данных.

Заключение

в этой главе мы исследовали множество типов данных SQL Server. Вы узнали о таких типах данных, как date, numeric, string, bit и BLOB, a также о выходящих за обычные ра.мки типах - timestamp и uniqueidentifier. Чтобы проектировать опти-матьиые базы данных и писать устойчивый код Transact-SQL, необходимо ближе познакомиться с разнообразием предоставляемых SQL Server типов данных. Их изучение - первый шаг к наннсаншо оптима;1ьиого кода для работы с ними.



Отсутствующие значения

Из тридцати шести альтернат лучшей является ггобе

Китайская пословиц

Отсутствующие значения и их правильная обработка - очень деликатная тем в сообществе пользователей баз данных. Все споры посвящены тому, как отсут ствующие значения должны храниться в реляционных базах да)нтых (и должн! ли вообще) и каким количеством и каки.ми типами лексе.м они должны быт представлены в SQL.

Существует, но крайней мере, три различные научные школы обработки от сутствующих значений. Изобретатель реляционных баз данных, д-р Е. Ф. Код пропагандирует две различные лексе.мы для представления отсутствующих зна чений: одну для представле)П1я значений, которые должны быть, но нх нет (на пример, пол человека), и одну для значений, которых вообще не должно быт1 так как они неприменимы (например, пол организации). Крис Дейт, известны: специалист по базам данных, принял позицию \ншнмалистов. Он считает, чт в SQL вообще не должно быть лексе.мы для представления отсутствующих зна чений. ANSI/ISO SQL-92 идет на компромисс и предоставляет одну уииверсаль )1ую лексе.му для отсутствующих значений: NULL

Рискуя показаться банальным, отмечу, что отсутствующие и пустые значения -это две большие разницы. Целое, значение которого отсутствует, это не то ж самое, что целое, значение которого равно нулю. Неопределенна^! строка - эт. )ie то же самое, что строка нулевой длины или строка, содержащая одни пробе лы. Эта разница важна, так как сравнения между пусты.ми и неопределенны.М! значениями всегда будут неудачны. Фактически, NULL-значения даже не равнг друг другу в таких сравнениях.

Возможность неопределенных значений в реляционнььх базах данных означает что для любого сравнения возможны три результата: Истина (True), Ложь (False или Неизвестно (Unknown). Конечно, это требует использования трехзначно! логики. Это показано в таблице истинности, представленной на рис. 3.L

Обратите внимание, что я использую NULL и Unknown, считая их взаимоз1 меняемыми, хотя с технической точки зрения это не так. NULL - значение даг



1 ... 5 6 7 8 9 10 11 ... 55
© 2004-2024 AVTK.RU. Поддержка сайта: +7 495 7950139 в тональном режиме 271761
Копирование материалов разрешено при условии активной ссылки.
Яндекс.Метрика