Quantcast
Channel: SQL.ru: Microsoft SQL Server
Viewing all articles
Browse latest Browse all 7251

Замена\объединение индексов на работающей системе

$
0
0
Привет!
Подскажите, пожалуйста, есть задача по объединению\оптимизации индексов. Довольно большая таблица, она есть на нескольких серверах с данными разных компаний (разные клиенты на разных серверах хранятся). Для примерна на одном из серверов в таблице более 600 млн. строк. На таблице есть 2 больших индекса с include. При этом dba жалуется, что некоторые процедуры при использовании этих индексов вызывают загрузку ЦПУ до 90%, если он перекомпилирует процедуру, то она использует кластерный индекс и загрузка ЦПУ падает до 15%.
Я нашла вот этот пост, который позволяет выбрать процедуры из планов в кэше, чтобы определить какие процедуры сейчас используют эти индексы.
[url=]https://www.sqlskills.com/blogs/jonathan/finding-what-queries-in-the-plan-cache-use-a-specific-index/[/url]

Вот скрипт, который используется
CREATE PROCEDURE spGetPlanUsingIndex
	@indexName NVARCHAR(128)
AS
BEGIN	
	SET NOCOUNT ON;

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 	

	-- Make sure the name passed is appropriately quoted 
	IF (LEFT(@IndexName, 1) <> '[' AND RIGHT(@IndexName, 1) <> ']') SET @IndexName = QUOTENAME(@IndexName); 

	WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
	INSERT INTO [dbo].[LogDataFileIndexUsage]
	(
		DBName,
		SPname, 
		ScanCount,
		SeekCount,
		UpdateCount,
		RefCount,
		UseCount,
		QueryPlan,
		IndexName
	)
	SELECT
		DB_NAME(E.dbid) AS [DBName],
		object_name(E.objectid, dbid) AS [ObjectName],
		E.query_plan.value('count(//RelOp[@LogicalOp = ''Index Scan'' or @LogicalOp = ''Clustered Index Scan'']/*/Object[@Index=sql:variable("@IndexName")])','int')  AS [ScanCount],
		E.query_plan.value('count(//RelOp[@LogicalOp = ''Index Seek'' or @LogicalOp = ''Clustered Index Seek'']/*/Object[@Index=sql:variable("@IndexName")])','int')  AS [SeekCount],
		E.query_plan.value('count(//Update/Object[@Index=sql:variable("@IndexName")])','int') AS [UpdateCount],	
		P.refcounts AS [RefCounts],
		P.usecounts AS [UseCounts],
		E.query_plan AS [QueryPlan],
		@IndexName
	FROM sys.dm_exec_cached_plans P
	CROSS APPLY sys.dm_exec_query_plan(P.plan_handle) E
	WHERE	
		E.query_plan.exist('//*[@Index=sql:variable("@IndexName")]') = 1
	OPTION(MAXDOP 1, RECOMPILE);
END


Кроме того попросила дать информацию о missing index на сервере. Список процедур получился небольшим – 10, что интересно одна и та же процедура могла использовать то один индекс то другой. На сервере включен ассинхронный режим обновления статистики. Я выбрала в каких запросах используются эти индексы в процедурах по планам из кэша, и собрала список полей, указанных в SELECT, WHERE и JOIN. А также поля , которые использовались как seek предикаты. Сделала один индекс без include полей, при тестировании вижу такую картину – его использует меньшее число процедур, но скорость работы примерно та же. Я ожидала, что вырастет загрузка CPU, но нет – все ок.
Я понимаю, что убирая include – нужно будет делать Key Lookup чтобы довыбрать нужные поля из таблицы, при анализе плана – можно видеть, что план со старым индексом несколько лучше. Но если изменения позволят сэкономить место + избавят от внезапного изменения загрузки по ЦПУ, то их стоит применить.
Буду благодарна, если поделитесь своими мыслями\опытом решения такой задачи.

Viewing all articles
Browse latest Browse all 7251

Trending Articles