031 Системный Администратор 06 2005

Page 48

администрирование го индекс (OrderDate), то, несмотря на ухудшение плана запроса, вы получите большой выигрыш на активно работающей базе данных. В самом деле при активной работе с заказами последней недели все страницы с данными большую часть времени будут находиться в памяти сервера. А сканирование диапазона дат в памяти, нужное для поиска данных по конкретному клиенту, как правило, быстрее, чем считывание с диска этих данных, даже по известному заранее адресу.

Не увлекайтесь созданием большого числа индексов Обычно при тестировании индексированных запросов используют всевозможные выборки (т.е. запросы, выполняющие чтение данных). Это понятно – выборки не разрушают данные. Но при этом упускается очень важный момент – при вставке, удалении, а часто и при обновлении данных индексы работают противоположным образом. Нет, они, конечно, помогают найти строчки, нуждающиеся в изменении. Но потом тратится куча времени на реорганизацию изменённых данных, и в итоге порой получается гораздо медленнее, чем на базе данных совсем без индексов. Именно поэтому стратегия «добавим индексы везде, где что-то тормозит», глобально проигрывает при попытке хоть чтото изменить в этой базе данных. Более пяти индексов на большой таблице является почти приговором для процессов, которые как-то пытаются изменять индексированные поля.

Самый главный совет – не следуйте советам В том числе и этому, да. Все советы даются для частных случаев, которые могут никогда не сложиться в вашей базе данных. Проверяйте. Меняйте индексы, делайте запросы и следите за производительностью. Анализ планов запросов – это мощнейший инструмент, но даже он порой даёт сбои и неправильно оценивает стоимость различных вариантов выполнения. Самый надёжный вариант – это в QA щелкнуть правой кнопкой в окне редактирования, выбрать Current Connection Properties, а там – галочки Set statistics time и Set statistics IO. И затем уже выполнить тестовый запрос. Уверяю вас, если время компиляции и выполнения

46

может зависеть от нагрузки сервера, число физических чтений определяется состоянием кэша страниц, то число логических чтений даёт почти идеальный параметр для оценки затрат на выполнение именно этого запроса. Ищите новые варианты, пробуйте их. Оптимизация индексов – это всегда очень интересно.

Управляем планами запросов Эта задача немного проще предыдущей. Если нужный индекс на базе данных уже есть, но MS SQL Server им почему-то не пользуется, то довольно просто уговорить его это сделать. Стоп, не тянитесь писать with (index=<ИмяИндекса?>)! Это тоже вариант, но он нужен на крайний случай. Предлагаю вам свой список мер: Выполните запрос dbcc freeproccache. Этот нехитрый запрос очищает кэш скомпилированных планов запроса и даёт серверу возможность перекомпилировать планы заново. Если сбой, нарушивший генерацию плана, был единичный, то новые алгоритмы окажутся правильными, и система оживёт. Но если вам приходится часто использовать dbcc freeproccache, то будьте внимательны – это может быть последствием какого-то неблагополучия сервера в целом. Cгенерируйте дополнительную статистику. Вот уж чего, как говорится, много не бывает. Её можно «навешивать» хоть на каждое поле. Главное – не забывать регулярно выполнять перегенерацию (а лучше создать задание для регулярного выполнения таких действий). Используйте подсказки для MS SQL Server, оставаясь в рамках стандарта ANSI-SQL. Предположим, что сервер выбрал использование индекса по полю, которое кажется вам наименее подходящим в такой ситуации. Всё просто – в секции запроса where пишите условие по этому полю не в виде прямого равенства или диапазона (например, Name = ‘Иван’), а с помощью функции COALESCE(<Имя поля>, <Имя поля>). Например, coalesce(Name, Name) = ‘Иван’. Это совершенно корректно математически, но при этом проблемный индекс по указанному полю не может быть использован. Другой пример –

представьте, что у вас есть условие типа where @Number like Code + ‘%’. Если бы запрос был построен как Code like @Number + ‘%’, сервер сам догадался бы использовать индекс по Code. Но в нашем варианте Code используется в составе сложного выражения, и оптимизатор пасует. Человеку же очевидно, что @Number like Code + ‘%’ может быть верно только тогда, когда @Number >= Code, так как у них одинаковые первые символы, но @Number длиннее. Вот тут и имеет смысл добавить в условия @Number >= Code, так как оно не изменит логики и поможет серверу самостоятельно избрать нужный запрос. Упростите запросы. Например, мне известны ситуации, в которых планы запросов сильно «плавали» при внешних соединениях (join) с представлениями (view), построенными на внешних соединениях. И только если всё предыдущее не помогло, используйте подсказки MS SQL Server. Они порой дают великолепный непосредственный результат, но с ними необходимо проявлять осторожность – в другой ситуации, на других данных или с другой загрузкой вынужденный план запроса иногда сильно деградирует. Немного сложнее приходится, в ситуации если вас устраивают выбранные индексы, но не устраивают методы и порядок слияния. MS SQL Server позволяет настраивать и эти моменты, но тут выбор возможностей очень ограничен. Вы можете сделать порядок соединений жёстко зависящим от порядка их упоминания в запросе (force order), выбрать метод соединения (loop|merge|hash join) или указать, что несколько строк в результирующем запросе вам нужны раньше других (FAST число строк). Будьте осторожны, выбирая соединение хэшированием (hash join). Оно даёт порой потрясающие результаты по производительности, но всегда требует очень много памяти. И когда вашему серверу перестанет ее хватать, такие запросы не только заметно деградируют по скорости, но сильно замедлят работу в целом. И наоборот, если сервер работает в состоянии нехватки оперативной памяти, изменение метода слияния с hash на loop может увеличить число логических чтений, но при этом волшеб-


Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.