Your SlideShare is downloading. ×
0
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Mssql opt
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Mssql opt

1,076

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,076
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Ядро SQL Server Database Engine может показывать, каким образом оно переходит к таблицам и использует индексы для доступа к данным или их обработки для запроса или другой инструкции DM, например для обновления. Это называется выводом плана выполнения. Для проведения анализа медленно выполняемого запроса полезно изучить план выполнения запроса, чтобы определить причину проблемы.
  • База наполнялась фиктивными данными с помощью программы SQL Data Generator от компании Red Gate
    (http://www.red-gate.com/products/sql_data_generator/index.htm)
  • Обратить внимание на использование статистики для базы данных
    Статистика используется оптимизатором запросов для построения наиболее эффективного плана выполнения запроса

    В нашем случае статистика будет отключена.
  • Ожидаемый план выполнения показывается сразу же.
    Реальный план выполнения – только после завершения выполнения запроса.

  • Замечания:
    - Стараться избегать подобных запросов, т.е. Выбирать те данные которые действительно необходимы в каждом конкретном случае.

  • Каждый узел древовидной структуры представлен в виде значка, указывающего логический и физический оператор, используемый для выполнения этой части запроса или инструкции.
    Каждый узел связан со своим родительским узлом. Дочерние узлы одного родительского узла отображаются в одном столбце. Однако все узлы в одном столбце не обязательно имеют общий родительский узел. Правила со стрелками на конце соединяют каждый узел с его родителем.
    Операторы показаны в виде символов, связанных с определенным родительским узлом.
    Ширина стрелки пропорциональна количеству строк. Если имеются данные о фактическом количестве строк, используются эти данные. В противном случае используется ориентировочное количество строк.
    Если запрос содержит несколько инструкций, показывается несколько планов выполнения запроса.
  • Для графического представления плана выполнения запроса студия использует SHOWPLAN_XML

    Оператор Clustered Index Scan сканирует кластеризованный индекс, заданный в столбце Аргумент плана выполнения запроса. При наличии необязательного предиката WHERE:(), возвращаются только строки, удовлетворяющие предикату. Если столбец Argument содержит предложение ORDERED, обработчик запросов требует, чтобы выходные данные строк были возвращены в порядке, в соответствии с которым они были отсортированы в кластеризованном индексе. Если предложение ORDERED отсутствует, подсистема хранилища выполняет поиск в индексе оптимальным способом, без обязательной сортировки выходных данных.
    Clustered Index Scan является логическим и физическим оператором.
  • Студия предлагает создать индекс

    Нажимаем правую клавишу мыши и выбираем «Missing Index Details…»
  • Полный текст предложения о создании индекса
  • Создаем рекомендованный индекс с именем idx_price_name
    С дополнительным полем Name
  • Index Seek – наиболее благоприятный вариант при выборке данных

    Оператор Clustered Index Seek использует поисковые возможности индексов для получения строк из кластеризованного индекса. Столбец Аргумент содержит имя используемого кластеризованного индекса и предикат SEEK:() SEEK:(). Подсистема хранилища использует индекс для обработки только тех строк, которые удовлетворяют данному предикату SEEK:(). SEEK:(). Он также может содержать предикат WHERE:(), который подсистема хранилища применяет для всех строк, которые удовлетворяют предикату SEEK:(), но предикат WHERE:() необязателен и не использует индексы для завершения процесса.

    OBJECT:([demo].[dbo].[Products].[idx_price_name] AS [p]), SEEK:([p].[Price] >= CONVERT_IMPLICIT(decimal(18,2),[@1],0) AND [p].[Price] <= CONVERT_IMPLICIT(decimal(18,2),[@2],0)) ORDERED FORWARD
  • Подробная информация по плану выполнения запроса
  • Немного «усложненный» запрос. Суть его в следующем:
    «Выбираем всех потребителей, которые приобрели конкретный продукт.»
  • Выполним запрос, для того чтобы постореть на временные затраты

    У каждой операции есть свой вес(%)

    Оператор Hash Match строит хэш-таблицу при помощи вычисления хэш-значения для каждой строки из своих входных данных. Предикат HASH:() со списком столбцов, использованных для создания хэш-значения, отображается в столбце Argument. Затем для каждой тестовой строки (если возможно) он вычисляет хэш-значение (с использованием той же хэш-функции) и осуществляет поиск совпадений по хэш-таблице. Если наличествует остаточный предикат (определенный посредством RESIDUAL:() в столбце Argument), строки должны удовлетворять также и этому предикату, чтобы рассматриваться в качестве совпадающих. 

    Оператор Merge Join выполняет внутреннее соединение, левое внешнее соединение, левое полусоединение, левое антиполусоединение, правое внешнее соединение, правое полусоединение, правое антиполусоединение, а также логические операции соединения.

    Студия рекомендует создать индекс.



  • Создаем рекомендованный индекс с именем idx_ProductId
    OrderId помещаем в дополнительное поле
  • Проверяем ожидаемый план выполнения запроса после создания рекомендованного индекса

    Мы видим, что план выполнения радикально изменился
    Сканирование индекса заменилось на поиск по индексу (стоимость/вес операции стал 11%)
    Соеденения с помощью хеширования заменено на соединение с помощью Вложенных циклов

    Оператор Nested Loops выполняет логические операции внутреннего соединения, левого внешнего соединения, левого полусоединения и антилевого полусоединения.
    Соединения вложенных циклов выполняют поиск во внутренней таблице для каждой строки внешней таблицы, обычно используя индекс. Опираясь на предполагаемые затраты, сервер Microsoft SQL Server решает вопрос о необходимости сортировки внешней таблицы, чтобы улучшить район поиска по индексу во внутренней таблице.

    В большинстве случаев Nested Loops предпочтительнее, чем Hash Match

    Помотрим, каковы временные затраты на выполнение запроса


  • Еще один схожий запрос –
    Ищем клиентов, которые купили что-нибудь в декабре 2000 г.
  • Мы снова видим рекомендации по созданию индекса
  • Создаем рекомендуемый индекс
    И опять выполняем запрос
  • IndexScan с весом в 68% заменился на IndexSeek с долей 6%

    Сравним выполнение запроса с индексом и без него
  • Совсем коротко о том, как меняется план выполнения в зависимости от условия

    Сначала выполним поск товаров купленных в декабре 2000г в ценовом диапазоне от 50 до 100 денежных единиц
  • Убираем ценовое ограничение
  • Мы видим, что план запроса изменился радикально.

    Над операторами, выполняющимися параллельно, отображается значок параллельного процесса.


    И нет никаких рекомендаций по индексам.
    Также следует обратить внимание на толщину стрелок, соединяющих пиктограммы процессов


    Время выполнения увеличилось также радикально.
  • Pinalkumar Dave is a Microsoft SQL Server MVP and a Mentor for Solid Quality India. He has written over 1300 articles on the subject on his blog athttp://blog.sqlauthority.com. 


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

    Бывают случаи (довольно редко), когда приходится в запросе указывать какой именно индекс надо использовать при построении плана запроса.
  • Transcript

    • 1. Использование Microsoft SQL Management Studio при оптимизации запросов.
    • 2. • Microsoft Windows Server 2003 • Microsoft SQL Server 2008 • Microsoft SQL Server Management Studio
    • 3. База данных
    • 4. Количество записей • Customers – 10 тыс. • OrderItems – 500 тыс. • Products – 200 тыс. • Orders – 100 тыс.
    • 5. Ожидаемый план выполнения Реальный план выполнения Статистика выполнения запроса
    • 6. SELECT * FROM [Products] as p SQL Server Execution Times: CPU time = 204 ms, elapsed time = 12409 ms. SELECT p.[ID], p.[Name] FROM [Products] as p SQL Server Execution Times: CPU time = 141 ms, elapsed time = 3547 ms.
    • 7. SELECT p.[ID], p.[Name] FROM [Products] as p
    • 8. SELECT p.[ID], p.[Name] FROM [Products] as p
    • 9. SELECT p.[ID], p.[Name] FROM [Products] as p
    • 10. SELECT p.[Name], p.[Price] FROM [Products] AS p WHERE p.[Price] BETWEEN 10 and 100 SQL Server Execution Times: CPU time = 62 ms, elapsed time = 21 ms. (1794 row(s) affected)
    • 11. Missing index /* Missing Index Details from SQLQuery2.sql The Query Processor estimates that implementing the following index could improve the query cost by 93.0671%. */ /* USE [demo] GO CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] ON [dbo].[Products] ([Price]) INCLUDE ([Name]) GO */
    • 12. Создаем индекс USE [demo] GO CREATE NONCLUSTERED INDEX [idx_price_name] ON [dbo].[Products] ([Price]) INCLUDE ([Name]) GO
    • 13. SELECT p.[Name], p.[Price] FROM [Products] AS p WHERE p.[Price] BETWEEN 10 and 100 SQL Server Execution Times: CPU time = 0 ms, elapsed time = 13 ms. (1794 row(s) affected)
    • 14. SELECT DISTINCT с.[ID], c.[FirstName], c.[LastName] FROM [OrderItems] AS oi LEFT JOIN [Orders] AS o ON o.[ID] = oi.[OrderId] LEFT JOIN [Customers] AS c ON o.[CustomerId] = c.[ID] WHERE oi.[ProductID] = 123
    • 15. Ожидаемый план SQL Server Execution Times: CPU time = 47 ms, elapsed time = 45 ms.
    • 16. Создаем индекс USE [demo] GO CREATE NONCLUSTERED INDEX [idx_ProductId] ON [dbo].[OrderItems] ([ProductId]) INCLUDE ([OrderId]) GO
    • 17. Ожидаемый план SQL Server Execution Times: CPU time = 0 ms, elapsed time = 2 ms.
    • 18. SELECT DISTINCT с.[ID], c.[FirstName], c.[LastName] FROM [OrderItems] AS oi LEFT JOIN [Orders] AS o ON o.[ID] = oi.[OrderId] LEFT JOIN [Customers] AS c ON o.[CustomerId] = c.[ID] WHERE oi.[ProductID] = 123 Без индекса по ProductId: C индексом: SQL Server Execution Times: CPU time = 47 ms, elapsed time = 45 ms. (3 row(s) affected) SQL Server Execution Times: CPU time = 0 ms, elapsed time = 2 ms. (3 row(s) affected)
    • 19. SELECT DISTINCT c.[ID], c.[FirstName], c.[LastName] FROM [Customers] as c JOIN Orders as o on o.[CustomerId] = c.[ID] WHERE o.[Date] >= '12.01.2000' AND o.[Date]< '01.01.2001'
    • 20. Ожидаемый план
    • 21. /* Missing Index Details from SQLQuery5.sql The Query Processor estimates that implementing the following index could improve the query cost by 67.9358%. */ /* USE [demo] GO CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] ON [dbo].[Orders] ([Date]) INCLUDE ([CustomerId]) GO */
    • 22. USE [demo] GO CREATE NONCLUSTERED INDEX [idx_Date] ON [dbo].[Orders] ([Date]) INCLUDE ([CustomerId]) GO
    • 23. С индексом: SQL Server Execution Times: CPU time = 0 ms, elapsed time = 13 ms. (843 row(s) affected) Без индекса: SQL Server Execution Times: CPU time = 16 ms, elapsed time = 81 ms. (843 row(s) affected)
    • 24. SELECT DISTINCT p.[ID], p.[Name] FROM [Products] AS p JOIN [OrderItems] AS oi ON oi.[ProductId]=p.[ID] JOIN [Orders] as o on o.[ID] = oi.[OrderId] WHERE o.[Date] >= '12.01.2000' AND o.[Date]< '01.01.2001' AND p.Price BETWEEN 50 and 100
    • 25. План выполнения SQL Server Execution Times: CPU time = 16 ms, elapsed time = 14 ms. (30 row(s) affected)
    • 26. SELECT DISTINCT p.[ID], p.[Name] FROM [Products] AS p JOIN [OrderItems] AS oi ON oi.[ProductId]=p.[ID] JOIN [Orders] as o on o.[ID] = oi.[OrderId] WHERE o.[Date] >= '12.01.2000' AND o.[Date]< '01.01.2001'
    • 27. План выполнения SQL Server Execution Times: CPU time = 329 ms, elapsed time = 243 ms. (4305 row(s) affected)
    • 28. Ссылки http://msdn.microsoft.com/ru-ru/library/ms191227(v=SQL.100).aspx (Анализ запроса) http://msdn.microsoft.com/en-us/library/ms191426(v=SQL.100).aspx (Advanced Query Tuning Concepts) http://msdn.microsoft.com/ru-ru/library/ms178071(v=SQL.100).aspx (Графическое отображение планов выполнения) http://msdn.microsoft.com/en-us/library/ms178071(v=SQL.100).aspx (Displaying Graphical Execution Plans) http://www.red-gate.com/products/sql_data_generator/index.htm (SQL Data Generator) http://blog.sqlauthority.com

    ×