Когда у вас есть запрос или хранимая процедура, требующие настройки производительности, что вы делаете в первую очередь?
Я согласен, что это неконструктивно и можно поискать в гугле, но почему у него 118 уф ?! :)


Посмотрите на предложение where - проверьте использование индексов / убедитесь, что ничего глупого не делается
where SomeComplicatedFunctionOf(table.Column) = @param --silly
Предполагая, что здесь MySQL, используйте EXPLAIN, чтобы узнать, что происходит с запросом, убедитесь, что индексы используются максимально эффективно, и попытайтесь исключить сортировку файлов. Высокая производительность MySQL: оптимизация, резервное копирование, репликация и многое другое - отличная книга по этой теме, как и Блог о производительности MySQL.
Это хорошо для MySQL, но вопрос был помечен как «sqlserver». Тем не менее, это хорошо. Аналогичным образом в SSMS можно использовать «Показать предполагаемый план выполнения» и «Включить фактический план выполнения». Если вы можете отказаться от сканирования огромных таблиц и использовать поиск по кластеризованному индексу, то вы на пути к оптимальной производительности.
@ DavidM
Assuming MySQL here, use EXPLAIN to find out what is going on with the query, make sure that the indexes are being used as efficiently as possible...
В SQL Server план выполнения дает вам то же самое - он сообщает вам, какие индексы используются и т. д.
Обычно я начинаю с объединений - я выбиваю каждое из них из запроса по одному и повторно запускаю запрос, чтобы понять, есть ли конкретное соединение, с которым у меня проблемы.
Индексируйте таблицы по критериям, которые вы отфильтровываете
Иногда в SQL Server, если вы используете OR в предложении where, это действительно снижает производительность. Вместо использования ИЛИ просто сделайте два выбора и объедините их вместе. Вы получаете те же результаты на 1000-кратной скорости.
Я видел это необъяснимое поведение.
Не обязательно трюк с производительностью SQL как таковой, но определенно связанный:
Хорошей идеей было бы использовать memcached, где это возможно, поскольку это было бы намного быстрее, просто извлекая предварительно скомпилированные данные непосредственно из памяти, а не из базы данных. Также есть разновидность MySQL, в которую встроен memcached (сторонний).
Во все мои временные таблицы я люблю добавлять уникальные ограничения (где это необходимо) для создания индексов и первичные ключи (почти всегда).
declare @temp table(
RowID int not null identity(1,1) primary key,
SomeUniqueColumn varchar(25) not null,
SomeNotUniqueColumn varchar(50) null,
unique(SomeUniqueColumn)
)
Убедитесь, что длина вашего индекса как можно меньше. Это позволяет БД читать больше ключей из файловой системы за раз, тем самым ускоряя ваши соединения. Я предполагаю, что это работает со всеми БД, но я знаю, что это конкретная рекомендация для MySQL.
Я люблю использовать
isnull(SomeColThatMayBeNull, '')
Над
coalesce(SomeColThatMayBeNull, '')
Когда мне не нужна поддержка нескольких аргументов, которую дает вам coalesce.
http://blog.falafel.com/2006/04/05/SQLServerArcanaISNULLVsCOALESCE.aspx
Не ставьте перед именами хранимых процедур префикс «sp_», потому что все системные процедуры начинаются с «sp_», и SQL Server будет труднее искать вашу процедуру при ее вызове.
Вы действительно тестировали это? Если SQL Server делает то, что разумно (используя алгоритм хеширования для поиска хранимой процедуры), это не имеет значения. Фактически, если SQL Server не было делает это, кажется, что производительность системы будет вонять (поскольку он предположительно вызывает свои собственные процедуры).
Думаю, это попадает в корзину преждевременной оптимизации. Вероятно, это хорошая практика, чтобы не вводить людей в заблуждение, но в качестве совета по оптимизации ... D-
Немного не по теме, но если вы контролируете эти проблемы ...
Высокий уровень и высокая отдача.
+1 за включение плохих отступов. Форматирование - ключ к успеху! :)
Я ищу:
Я взял за привычку всегда использовать переменные связывания. Возможно, переменные связывания не помогут, если СУБД не кэширует операторы SQL. Но если вы не используете переменные связывания, у РСУБД нет возможности повторно использовать планы выполнения запросов и проанализированные операторы SQL. Экономия может быть огромной: http://www.akadia.com/services/ora_bind_variables.html. Я работаю в основном с Oracle, но Microsoft SQL Server работает примерно так же.
По моему опыту, если вы не знаете, используете ли вы переменные связывания, скорее всего, нет. Если ваш язык приложения не поддерживает их, найдите тот, который поддерживает. Иногда вы можете исправить запрос A, используя переменные связывания для запроса B.
После этого я разговариваю с нашим администратором баз данных, чтобы выяснить, что причиняет РСУБД наибольшую боль. Обратите внимание, что вы не должны спрашивать «Почему этот запрос медленный?» Это все равно, что попросить врача удалить вам аппендикс. Конечно, проблема может быть в вашем запросе, но так же вероятно, что что-то еще не так. Как разработчики, мы склонны мыслить строчками кода. Если линия медленная, исправьте эту линию. Но СУБД - действительно сложная система, и ваш медленный запрос может быть признаком гораздо более серьезной проблемы.
Слишком много советов по настройке SQL - кумиры карго. В большинстве случаев проблема не связана или минимально связана с синтаксисом, который вы используете, поэтому обычно лучше использовать самый чистый синтаксис, который вы можете. Затем вы можете начать искать способы настройки базы данных (а не запроса). Изменяйте синтаксис только тогда, когда это не удается.
Как и при любой настройке производительности, всегда собирайте значимую статистику. Не используйте время настенных часов, если это не настраивается пользователем. Вместо этого посмотрите на такие вещи, как время ЦП, извлеченные строки и блоки, считанные с диска. Слишком часто люди оптимизируют не для того.
@Terrapin есть еще несколько отличий между isnull и coalesce, которые стоит упомянуть (помимо соответствия ANSI, что для меня очень важно).
SET NOCOUNT ON
Обычно это первая строка внутри моих хранимых процедур, если мне действительно не нужно использовать @@ROWCOUNT.
@@ ROWCOUNT все равно устанавливается. NOCOUNT отключает инструкции «затронутых строк xx».
Действительно ли это когда-нибудь дает заметную разницу в производительности?
Да, тогда счетчик не рассчитывается автоматически каждый раз, когда выполняется инструкция SQL. Достаточно легко протестировать запрос с учетом и без него, чтобы увидеть, насколько он важен.
В любом случае счетчик отслеживается в SQL Server. Любая разница в производительности, которую вы видите, связана с тем, что счетчики должны проходить по сети на ваш интерфейс. Если вы делаете один SELECT, это не будет иметь заметного значения. Если у вас есть цикл со 100000 вставками, это намного больше по сети.
set transaction isolation level read uncommitted
Предотвращает мертвые блокировки, когда целостность транзакции не является абсолютно необходимой (что обычно верно)
Да, но это может привести к странным ошибкам, которые ОЧЕНЬ сложно найти.
Удалите курсоры там, где они не нужны.
Ага, курсоры - это проклятие! ;)
Фу. Не выбрасывайте это так безоговорочно. Курсоры похожи на пистолеты. Они не плохи сами по себе, просто люди делают с ними действительно плохие вещи.
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)
Это связано с тем, что меньшее количество автомобилей соответствует цене, чем выбор цвета, что дает механизму запросов гораздо меньше данных для анализа.
Известно, что у меня есть два очень похожих индекса, различающихся только порядком полей для ускорения запросов (имя, фамилия) в одном и (фамилия, имя) в другом.
Первый шаг:
Посмотрите на план выполнения запроса!
TableScan -> bad
NestedLoop -> предупреждение
TableScan за вложенной петлей -> DOOM!
УСТАНОВИТЬ СТАТИСТИКУ IO ON
ВКЛЮЧИТЬ ВРЕМЯ СТАТИСТИКИ
Вот удобный список вещей, которые я всегда даю тем, кто спрашивает меня об оптимизации. В основном мы используем Sybase, но большинство советов применимы ко всем.
SQL Server, например, поставляется с множеством битов для мониторинга / настройки производительности, но если у вас нет ничего подобного (а может быть, даже если у вас есть), я бы подумал о следующем ...
Я видел, что 99% проблем вызвано установкой слишком много таблиц в объединении. Чтобы исправить это, нужно выполнить половину соединения (с некоторыми таблицами) и кэшировать результаты во временной таблице. Затем выполните остальную часть запроса, присоединившись к этой временной таблице.
#temp могут работать намного лучше, чем переменные @table с большими объемами (тысячи строк).о каком бите вы имеете в виду?
Это классная штука, но я бы хотел, чтобы у вас были ссылки на некоторые претензии. Например: я никогда не слышал, чтобы оптимизация учитывала только 4 таблицы за раз в соединении. Я не понимаю, как это могло быть правильно. Не могли бы вы дать некоторые ссылки, в частности, на это? Я бы хотел посмотреть, откуда вы это берете.
В SQL Server используйте директиву nolock. Это позволяет команде select завершиться без ожидания - обычно заканчиваются другие транзакции.
SELECT * FROM Orders (nolock) where UserName = 'momma'
NOLOCK предназначен только для запросов, для которых вас не интересуют правильные результаты.
Выполнение запроса с использованием WITH (NoLock) для меня в значительной степени является стандартной операцией. Любой, кто поймал выполнение запросов к таблицам размером в десятки гигабайт, без этого вынимается и расстреливается.
Это следует использовать с умом, а не по привычке. Блокировка - это не зло, это просто неправильно.
Недавно я усвоил трюк: 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.aspx
Я всегда сначала использую SQL Profiler (если это хранимая процедура с большим количеством уровней вложенности) или планировщик выполнения запросов (если это несколько операторов SQL без вложенности). В 90% случаев вы можете сразу найти проблему с помощью одного из этих двух инструментов.
Преобразуйте запросы NOT IN в LEFT OUTER JOINS, если это возможно. Например, если вы хотите найти все строки в 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
Удалите вызовы функций в Sprocs, где много строк будут вызывать функцию.
Мой коллега использовал вызовы функций (например, получение lastlogindate из идентификатора пользователя) для возврата очень широких наборов записей.
Задавшись оптимизацией, я заменил вызовы функций в sproc на код функции: у меня время работы многих sproc уменьшилось с> 20 секунд до
Вот несколько хитростей Оптимизация запросов SQL Server