Найгірші методи (MS SQL Server) – використання неуточнених імен, Інші СУБД, Бази даних, статті

Коли Енді недавно додав одну частину в ряду Гірших Методів – про непродуманому додаванні стовпця, Це змусило мене згадати про гіршій практиці, з якою я намагаюся боротися протягом довгого часу. Можливо, вона не настільки специфічна, як більшість інших гірших методів, але причина одного з гірших методів, за якими я часто стикаюся, – це пересічна лінь. Однією з помилок, яку люди часто допускають тільки тому, що вони ліниві, є те, що імена об’єктів не уточнюються ім’ям власника. Я збираюся обговорити це тут, а в наступній статті я хочу обговорити деякі інші помилки, причиною яких є лінь.


Використання уточнених імен


Ніколи не забувайте уточнювати назви об’єктів ім’ям власника об’єкта. Це покращує продуктивність, по крайней мере, в силу двох причин. Перш за все, коли Ви визначаєте ім’я об’єкта, не уточнюючи його ім’ям власника, SQL Server буде спочатку шукати об’єкт, що належить поточним працює користувачеві. Якщо такий об’єкт не буде знайдено, буде використаний об’єкт з тим же самим ім’ям, але належить dbo. Так, якщо користувач на ім’я John підключився до Northwind і виконує SELECT OrderID FROM Orders, SQL Server буде шукати об’єкт John.Orders в Northwind, і в разі його відсутності буде використаний dbo.Orders. Якби він замість цього виконав запит SELECT OrderID FROM dbo.Orders, SQL Server не потрібно було б шукати об’єкт на ім’я John.Orders. Це не може істотно вплинути на продуктивність, але ж важливо також уникнути використання несподіваного об’єкта. Уявіть, що додаток авторизується як користувач John і виконує оператор SELECT OrderID FROM Orders. Це працює чудово до того дня, поки хтось під логіном John не вирішить створити таблицю з ім’ям John.Orders (з тієї чи іншої причини). Тепер додаток раптово почне повертати OrderIDs з нової таблиці John.Orders, і цю помилку можна дуже довго шукати.


Інша причина підвищення продуктивності в результаті уточнення імен об’єкта ім’ям власника полягає в тому, що є хороший шанс, що SQL Server буде багаторазово використовувати плани виконання для операторів, записаних саме таким чином. Наприклад, якщо Ви використовуєте sp_executesql, щоб виконати динамічні оператори SQL, Ви дійсно використовувати повністю уточнені імена об’єктів, щоб SQL Server повторно використав плани виконання. Повністю уточнене ім’я об’єкта означає визначення всіх його чотирьох частин, то є. Имя_сервера.имя_базы.имя_владельца.имя_объекта. Якщо Ви опустите будь-яку з них, буде використовуватися значення за замовчуванням. Сервер за замовчуванням і база даних – це звичайно сервер і база даних, на яких виконується запит, а імя_владельца за замовчуванням – це, як і раніше, dbo. Але навіть при тому, що використовується ім’я за замовчуванням, SQL Server не буде повторно використовувати план виконання для операторів, інакше специфікує уточнені імена об’єктів. Ви можете побачити це самі в SQL Profiler, виконавши наступний невеликий скрипт. Стартуйте Profiler і підключіть його до вашого серверу. Додайте всі події в класі подій Stored Procedures (збережені процедури) і видаліть всі інші події.


DECLARE @sql nvarchar(200)
DECLARE @params nvarchar(100)
DECLARE @intvar int

– Створення оператора, використовуючи повністю уточнені імена
SET @sql = N”SELECT OrderID, CustomerID, EmployeeID FROM dbo.Orders WHERE EmployeeID = @empid”
SET @params = N”@empid int”
SET @intvar = 3
EXEC sp_executesql @sql, @params, @empid = @intvar

– Виконайте той же оператор ще раз, повторно використовуючи попередній план виконання
– Зауваження: SP: ExecContextHit в Profiler
SET @intvar = 4
EXEC sp_executesql @sql, @params, @empid = @intvar

– Той же оператор, але не використовує повністю уточнені імена
– Зауваження: тут немає SP: ExecContextHit в Profiler
SET @sql = N”SELECT OrderID, CustomerID, EmployeeID FROM Orders WHERE EmployeeID = @empid”
SET @params = N”@empid int”
SET @intvar = 4
EXEC sp_executesql @sql, @params, @empid = @intvar


Коли Ви запустите скрипт, то повинні побачити SP: CacheInsert, коли виконано перший запит, але коли він виконується знову, використовуючи тільки змінене значення @ empid, Ви натомість побачите SP: ExecContextHit. Це означає, що SQL Server зміг повторно використовувати план виконання. Нарешті, коли третій оператор виконаний, Ви знову побачите SP: CacheInsert, і це навіть при тому, що результат запиту не змінився в порівнянні з попереднім випадком. Причина, як я пояснив вище, полягає в тому, що другий оператор не уточнює ім’я Orders так, як це робилося в першому операторі.


Вказівка ​​імені власника важливо не тільки для виконання оператора SELECT. Не менш важливо, можливо, навіть більш важливо, уточнювати об’єкти ім’ям власника при їх створенні. Наприклад, якби Джон створив таблицю, не вказуючи її власника, то він сам став би цим власником. Це означає, що будь-який інший користувач, який захоче виконати оператор SELECT для цієї таблиці, повинен уточнювати ім’я таблиці його ім’ям, роблячи вибірку з неї. Якби вони також ніколи не забували уточнювати імена об’єктів, це була б не така велика проблема, але так як ми знаємо, що люди ледачі (або не знають, що означає уточнення імені), вони, ймовірно, будуть це робити далеко не завжди. Отже, коли Джон створює свою таблицю, його оператор повинен з CREATE TABLE dbo.TableName … Є, звичайно, винятки, коли Ви дійсно хочете створити таблицю з Джоном (John) як власника, але в таких випадках він повинен зазначити це, тобто написати CREATE TABLE John.TableName … Чому це важливо? Уявіть, що Джон створює цю таблицю в базі даних на тестовому сервері і зберігає оператор у вигляді скрипта. Пізніше, коли ця таблиця повинна бути створена в робочій базі даних, запустити скрипт міг хтось інший, в результаті чого таблиця отримає іншого власника.


Ще більш важливо уточнювати імена об’єктів, що використовуються всередині збереженої процедури. В іншому випадку, об’єкти, які не уточнені ім’ям власника і згадуються в операторах SELECT, INSERT, UPDATE і DELETE, за замовчуванням будуть приписані власнику збереженої процедури, а не людині, що виконує її. Знову таки, ці об’єкти могли б бути тими, що Ви і хочете, але завжди краще явно уточнювати ім’я. Якщо процедура використовується як механізм контролю доступу до даних в таблицях (тобто прямий доступ до таблиць обмежений, і всі користувачі повинні використовувати процедури, які вибирають з цих таблиць дані), ви можете зіткнутися з іншою проблемою. Якщо імена для цих таблиць, доступ до яких обмежений, не будуть уточнені в процедурі, то тільки творцеві процедури буде дозволений до них доступ.


Нарешті, якщо Ви не уточніть імена об’єктів, що використовуються в процедурах, що містять оператори CREATE / ALTER / DROP TABLE, TRUNCATE TABLE, CREATE / DROP INDEX, UPDATE STATISTICS, і командах DBCC, Ви можете зруйнувати систему. Причиною є те, що дозвіл імен об’єктів відбувається під час виконання; при цьому використовується ім’я користувача, який виконує процедуру в якості власника за замовчуванням для об’єктів, імена яких не повністю уточнені. Уявіть, що користувач Джейн має таблицю по імені Orders, де вона зберігає інформацію своїх замовлень. Тепер їй потрібно швидко і легко видалити цю інформацію, тому вона створює приблизно таку процедуру:


CREATE PROCEDURE TruncateOrders
AS
BEGIN
TRUNCATE TABLE Orders
END


Вона тестує процедуру, і та працює прекрасно, її таблиця Orders очищається. Потім вона переносить процедуру в робоче середовище. Коли одного разу Джону потрібно видалити дані з таблиці Orders, що належить Джейн, він виконує цю процедуру (виконуючи EXEC Jane.TruncateOrders). Здогадайтеся, що трапиться? Ну, якщо є таблиця з ім’ям John.Orders, то вона буде очищена, а якщо ні, то буде очищена dbo.Orders, оскільки dbo – це значення за замовчуванням, яке використовує SQL Server, коли не знаходить об’єкт, що належить поточному користувачеві.


Отже, з причин, розглянутих вище, я рекомендую Вам зробити своєю звичкою завжди уточнювати всі імена об’єктів, використовуючи синтаксис імя_владельца.імя_об’екта. І я кажу, що Ви повинні писати таким чином не тільки ваші процедури, я хочу, щоб Ви зробили своєю звичкою завжди поступати таким чином, навіть в тому випадку, коли ви пишете запити для швидкого одноразового виконання. Якщо Ви зробите це своєю звичкою, то ніколи не забудете це зробити, коли це виявиться дійсно необхідним і важливим.

Christoffer Hedgate (Оригінал: Worst Practice – Not Qualifying Objects With The Owner)
Переклад: Моісеєнко С.І.
Оригінал перекладу

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*