Коли у вас є запит або збережена процедура, яка потребує налаштування продуктивності, які з перших речей ви спробуєте?
Коли у вас є запит або збережена процедура, яка потребує налаштування продуктивності, які з перших речей ви спробуєте?
Відповіді:
Ось зручний перелік речей, які я завжди дарую комусь, запитуючи мене про оптимізацію.
Ми в основному використовуємо Sybase, але більшість порад застосовуватимуться в усіх напрямках.
Наприклад, SQL Server постачається з безліччю бітів моніторингу / налаштування продуктивності, але якщо у вас немає нічого подібного (а може бути, навіть якщо ви робите), я б розглядав наступне ...
99% проблем, які я бачив, викликані введенням занадто багато таблиць в об'єднання . Виправлення цього полягає в тому, щоб зробити половину з'єднання (з деякою з таблиць) та кешувати результати у тимчасовій таблиці. Потім виконайте решту запитів, приєднавшись до цього тимчасового столу.
#temp
таблиці можуть працювати набагато краще, ніж @table
змінні з великими обсягами (тисячі рядків).Трохи поза темою, але якщо у вас є контроль над цими питаннями ...
Високий рівень та високий вплив.
CREATE INDEX
Переконайтеся, що є ваші індекси WHERE
та JOIN
пункти. Це значно пришвидшить доступ до даних.
Якщо ваше оточення - це дані або склад даних, індекси повинні бути рясні для практично будь-якого можливого запиту.
У транзакційному середовищі кількість індексів має бути нижчою, а їх визначення більш стратегічними, щоб підтримка індексу не затягувала ресурси. (Підтримка індексу - це коли листя індексу потрібно змінити, щоб відобразити зміну базової таблиці, як INSERT, UPDATE,
і DELETE
операції.)
Також пам’ятайте про порядок полів в індексі - чим більш вибірковим (вища кардинальність) є поле, тим раніше в індексі воно повинно з’являтися. Наприклад, скажіть, що ви запитуєте про вживані автомобілі:
SELECT i.make, i.model, i.price
FROM dbo.inventory i
WHERE i.color = 'red'
AND i.price BETWEEN 15000 AND 18000
Ціна, як правило, має вищу кардинальність. Доступно лише кілька десятків кольорів, але цілком можливо тисячі різних запитуваних цін.
З цих варіантів вибору індексу idx01
передбачено швидший шлях до задоволення запиту:
CREATE INDEX idx01 ON dbo.inventory (price, color)
CREATE INDEX idx02 ON dbo.inventory (color, price)
Це тому, що менше автомобілів задовольнять цінову точку, ніж вибір кольору, даючи механізму запиту набагато менше даних для аналізу.
Мені відомо, що є два дуже схожих індексу, що відрізняються лише польовим порядком для швидкого запиту (ім'я, прізвище) в одному і (прізвище, ім'я) в іншому.
Нещодавно я дізнався, що SQL Server може оновлювати локальні змінні, а також поля, в операторі оновлення.
UPDATE table
SET @variable = column = @variable + otherColumn
Або більш читаною версією:
UPDATE table
SET
@variable = @variable + otherColumn,
column = @variable
Я використовував це для заміни складних курсорів / з'єднань при здійсненні рекурсивних обчислень, а також отримав багато продуктивності.
Ось деталі та приклад коду, який зробив фантастичні покращення продуктивності: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running-totals-in-sql-server-2005---the-optimal. асп
Якщо припустити MySQL тут, використовуйте EXPLAIN, щоб дізнатися, що відбувається з запитом, переконайтесь, що індекси використовуються максимально ефективно та спробуйте усунути різновиди файлів. Висока продуктивність MySQL: оптимізація, резервне копіювання, реплікація та багато іншого - це чудова книга на цю тему, як і Блог продуктивності MySQL .
@Terrapin Є кілька інших відмінностей між isnull і coalesce, які варто згадати (крім відповідності ANSI, яка для мене велика).
Я, як правило, розпочну з об'єднань - я вибиваю кожного із них із запиту один за одним і повторно запускаю запит, щоб отримати уявлення, чи є певне приєднання, з яким я маю проблеми.
У всіх моїх тимчасових таблицях я люблю додавати унікальні обмеження (де це можливо) для індексів та первинних ключів (майже завжди).
declare @temp table(
RowID int not null identity(1,1) primary key,
SomeUniqueColumn varchar(25) not null,
SomeNotUniqueColumn varchar(50) null,
unique(SomeUniqueColumn)
)
Я зробив звичку завжди використовувати змінні змінні. Можливо, змінні змінні не допоможуть, якщо RDBMS не кешує оператори SQL. Але якщо ви не використовуєте змінні прив'язки, RDBMS не має шансу повторно використовувати плани виконання запитів та проаналізувати оператори SQL. Економія може бути величезною: http://www.akadia.com/services/ora_bind_variables.html . Я працюю в основному з Oracle, але Microsoft SQL Server працює майже так само.
На моєму досвіді, якщо ви не знаєте, використовуєте чи ні, використовуєте змінні прив’язки, ви, мабуть, не так. Якщо мова вашої програми не підтримує їх, знайдіть цю програму. Іноді ви можете виправити запит A, використовуючи прив'язні змінні для запиту B.
Після цього я розмовляю з нашою DBA, щоб дізнатися, що викликає RDBMS найбільше болю. Зауважте, що не слід запитувати "Чому цей запит повільний?" Це як би попросити лікаря вийняти вам додаток. Впевнені, що ваш запит може бути проблемою, але це так само ймовірно, що щось інше піде не так. Як розробники ми схильні мислити з точки зору рядків коду. Якщо лінія повільна, виправте її. Але RDBMS - це дійсно складна система, і ваш повільний запит може бути симптомом набагато більшої проблеми.
Занадто багато підказок щодо налаштування SQL - кумири з вантажних культів. Більшість випадків ця проблема не пов'язана або мінімально пов'язана з використовуваним вами синтаксисом, тому зазвичай найкраще використовувати найчистіший синтаксис, який ви можете. Тоді ви можете почати шукати способи налаштування бази даних (не запит). Налаштуйте синтаксис лише тоді, коли це не вдасться.
Як і будь-яка настройка продуктивності, завжди збирайте змістовну статистику. Не використовуйте час настінних годин, якщо це не налаштування користувача, яке ви налаштовуєте. Замість цього подивіться на такі речі, як час процесора, вилучені рядки та блоки зчитування з диска. Занадто часто люди оптимізуються для неправильної речі.
Якщо можливо, перетворіть НЕ в запити, щоб ЛІТИШЕ ВНІШНІ ПРИЄДНАННЯ Наприклад, якщо ви хочете знайти всі рядки в Table1, які не використовуються за допомогою зовнішнього ключа в Table2, ви можете зробити це:
SELECT *
FROM Table1
WHERE Table1.ID NOT IN (
SELECT Table1ID
FROM Table2)
Але ви отримуєте набагато кращі показники завдяки цьому:
SELECT Table1.*
FROM Table1
LEFT OUTER JOIN Table2 ON Table1.ID = Table2.Table1ID
WHERE Table2.ID is null
@ DavidM
Якщо припустити MySQL тут, використовуйте EXPLAIN, щоб дізнатися, що відбувається з запитом, переконайтесь, що індекси використовуються максимально ефективно ...
У SQL Server план виконання отримує те саме - він говорить вам про те, які індекси потрапляють тощо.
Не обов’язково хитрість виконання SQL як така, але певно пов'язана:
Доброю ідеєю було б використовувати memcached, де це можливо, оскільки це було б набагато швидше, просто витягуючи попередньо складені дані безпосередньо з пам'яті, а не отримуючи їх з бази даних. Існує також аромат MySQL, який вбудований в пам'ять (третя сторона).
Переконайтеся, що довжина вашого індексу є якомога меншою. Це дозволяє БД одночасно читати більше ключів з файлової системи, тим самим прискорюючи приєднання. Я припускаю, що це працює з усіма БД, але я знаю, що це конкретна рекомендація для MySQL.
Я пильную:
SET NOCOUNT ON
Зазвичай перший рядок у моїх збережених процедурах, якщо мені насправді не потрібно використовувати @@ROWCOUNT
.
У SQL Server використовуйте директиву про блокування. Це дозволяє виконувати команду select без необхідності чекати - зазвичай інші операції закінчуються.
SELECT * FROM Orders (nolock) where UserName = 'momma'
Видаліть виклики функцій у програмах Sprocs, де функція буде викликати багато рядків.
Мій колега використовував виклики функцій (отримуючи lastlogindate від userid як приклад) для повернення дуже широких наборів записів.
Завдання оптимізації я замінив виклики функцій у прорості кодом функції: я отримав багато відростків часу від> 20 секунд до <1.
Мені подобається користуватися
isnull(SomeColThatMayBeNull, '')
Над
coalesce(SomeColThatMayBeNull, '')
Коли мені не потрібна підтримка декількох аргументів, яку надає вам сплетення.
http://blog.falafel.com/2006/04/05/SQLServerArcanaISNULLVsCOALESCE.aspx
Не префіксуйте імена збережених процедур з "sp_", оскільки всі системні процедури починаються з "sp_", і SQL Server доведеться шукати складніше, щоб знайти вашу процедуру, коли вона буде викликана.
set transaction isolation level read uncommitted
Запобігає загиблим блокуванням, коли цілісність транзакцій не є абсолютно необхідною (що зазвичай так)