통계 자동 갱신 조건과 별개로 옵티마이저 판단 SQL Server는 통계가 오래되거나 변경되면 자동으로 갱신하고 그때 계획을 다시 컴파일합니다. 하지만 통계 갱신이 없더라도, 데이터 분포 변화가 심해 기존 계획이 비효율적이라고 판단되면 옵티마이저가 강제 Recompile을 트리거할 수 있습니다.
DML로 인한 데이터 양 변화 예를 들어, 특정 테이블에 대량의 INSERT/DELETE가 발생해 행 수가 급격히 변하면, 기존 계획의 조인 전략(예: Nested Loop vs Hash Join)이 더 이상 적합하지 않을 수 있습니다. 이 경우 옵티마이저는 계획 캐시를 무효화하고 새 계획을 생성합니다. ü 대량 DML로 인해 통계 임계치 초과 시 자동 갱신 → 기존 계획의 카디널리티 추정이 틀려서 재컴파일 발생
옵션 및 힌트 영향 OPTION(RECOMPILE) 힌트가 있거나, 저장 프로시저에 WITH RECOMPILE이 설정된 경우 매 실행마다 새 계획을 생성합니다. 파라미터 스니핑으로 인해 특정 값에서 기존 계획이 비효율적일 때도 Recompile이 발생합니다.
메모리 압박 또는 캐시 제거 DBCC FREEPROCCACHE 실행, 메모리 부족으로 인한 캐시 제거 등도 재컴파일을 유발합니다.
스키마 변경 o ALTER TABLE, ALTER VIEW, 인덱스 생성/삭제 o 제약조건, 열 추가/삭제 → 계획이 참조하는 객체 구조가 바뀌면 무효화
SET 옵션 변경 ANSI_NULLS, QUOTED_IDENTIFIER 등 세션 옵션 변경 시
임시 테이블 변경 Temp Table 구조 변경, 인덱스 추가/삭제
기타 Query Store 강제 계획 적용 실패 데이터베이스 버전 변경 파티션 뷰 변경 등
또한 통계 갱신이 없더라도 옵티마이저는 내부 임계값을 기준으로 판단합니다.
예를 들어 특정 테이블에서 수백만 건의 INSERT가 발생하게 될 경우, 통계는 아직 갱신되지 않았지만, 옵티마이저는 기존 계획이 잘못될 가능성이 높다고 판단하여 Recompile을 수행할 수 있고, 파라미터 값 변화로 인해 기존 Plan이 비효율적으로 판단될 경우 Recompile을 수행할 수 있습니다.
Recompile이 발생하는 경우는 여러가지 이유가 있으며 테이블의 컬럼 및 인덱스 변경, Set옵션의 변경, 서버 재시작, 플랜캐시의 상황으로 캐시에서 밀려난 후 Compile, RECOMPILE 힌트, 명시적인 SP_Recompile등의 요소에 의해 발생할 수 있습니다.
해당 시간 전환 전/후로 아래와 같이 쿼리하여 현재SQL Server가 인지하는 시간값을retrieve하실 수 있으며,
혹시 해당 시간 전환이 잘 안 될 경우 서버에서 제대로 시간 변경이 안 되는 것이므로 이 때NTP서버와의 통신 상태 점검 및Windows레벨에서의 시간 설정을 확인해 보실 수 있습니다.
--1.현재 시간 확인 SELECT SYSDATETIMEOFFSET() AS now_with_offset; --2.조회 시점 폴란드Timezone DST적용 여부 확인 SELECT * FROM sys.time_zone_info WHERE name LIKE 'Central European%';
WRITELOG대기 원인 분석을 위해 성능 모니터와 세션 정보 수집을 권장 드립니다. 성능 카운터는 전반적인 시스템 상태를 확인하는 데 유용하며,세션 정보는 어떤 쿼리나 트랜잭션이WRITELOG대기를 발생시키는지 파악하고 세부 분석하는 데 도움이 됩니다. 수집 방법은 아래와 같습니다.
1. SQL성능 카운터 수집
Step1 cmd를 관리자권한으로 실행한 뒤 아래 명령을 실행하면 성능 수집기가 생성됩니다. 1초 주기로 최대 1024MB까지 수집되며,수집 경로는 환경에 맞게 수정해 주시기 바랍니다. WRITELOG대기 발생 시점을 알고 있는 경우,해당 짧은 기간 동안1초 간격으로 수집할 것을 권장 드립니다. 발생 시점을 알 수 없는 경우에는10~15초 간격으로 하루 정도 수집하는 것을 권장 드립니다.
CREATE DATABASE tmpMonitoringDB GO use tmpMonitoringDB GO select top(1) getdate() as ctime, db_name(der.database_id) as database_name, der.*, dest.text, des.program_name into dm_exec_requests_history from sys.dm_exec_requests as der inner join sys.dm_exec_sessions as des on der.session_id = des.session_id cross apply sys.dm_exec_sql_text(der.sql_handle) as dest GO truncate table dm_exec_requests_history GO
Step2 1초 단위로 루프를 수행하면서 세션 정보를 수집합니다. 무한 루프이므로 상황이 종료된 이후 쿼리를 직접 취소하시면 됩니다.
declare @startTime datetime = getdate() while 1=1 begin insert into dm_exec_requests_history select getdate() as ctime, db_name(der.database_id) as database_name, der.*, dest.text, des.program_name from sys.dm_exec_requests as der inner join sys.dm_exec_sessions as des on der.session_id = des.session_id cross apply sys.dm_exec_sql_text(der.sql_handle) as dest where der.session_id <> @@spid waitfor delay '00:00:01' end
-System metadata preparation to create the new empty index structure. -A snapshot of the table is defined. That is, row versioning is used to provide transaction-level read consistency. -Concurrent user write operations on the source are blocked for a short period. No concurrent DDL operations are allowed except creating multiple nonclustered indexes.
-S (Shared) on the table* -IS (Intent Shared) -INDEX_BUILD_INTERNAL_RESOURCE**
Build : Main phase
-The data is scanned, sorted, merged, and inserted into the target in bulk load operations. -Concurrent user select, insert, update, and delete operations are applied to both the pre-existing indexes and any new indexes being built.
-IS -INDEX_BUILD_INTERNAL_RESOURCE**
Final : Short phase
-All uncommitted update transactions must complete before this phase starts. -Depending on the acquired lock, all new user read or write transactions are blocked for a short period until this phase is completed. -System metadata is updated to replace the source with the target. -The source is dropped if it is required. For example, after rebuilding or dropping a clustered index.
-INDEX_BUILD_INTERNAL_RESOURCE** -S on the table if creating a nonclustered index.* -SCH-M (Schema Modification) if any source structure (index or table) is dropped.*
-다음은 온라인 인덱싱 작업에 대한 일반적인 가이드라인입니다. Online Indexing 작업 중 발생할 수 있는 여러가지 이슈사항과 사전 고려사항을 정리하고 있으며, Update 부하가 높은 환경에서 Online Indexing 중, 종종 발생하는 Deadlock(자동으로 해소)과 같은 증상도 해당 문서를 통해 확인할 수 있습니다.
##SQL Version :Microsoft SQL Server 2019 (RTM-CU17) (KB5016394) - 15.0.4249.2 (X64)
확인사항]
먼저 DTC실패(Error: 8509)기록된후 Rollback하는 과정에서 Dump가 생성으며, 해당 이슈는 이미 알려진 이슈로 CU21에서 FIX가 되었습니다.
해당 Dump는 in-memory Table사용과정에서 발생할수있으며, 고객사같은 경우는 DTC Transaction이 Rollback 되는 과정에서 해당 known issue로 인한 Dump가 생성었고 이로인한 가용성그룹이 Resolving상태로 빠지게됩니다.
이후 Leasetime out이 발생하나 FailureConditionLevel(2)로 Failover가 자동적으로 Triggered되지 않았습니다.
#ErrorLog.2 2024-04-02 14:01:03.93 spid62 Error: 8509, Severity: 16, State: 1. 2024-04-02 14:01:03.93 spid62 Import of Microsoft Distributed Transaction Coordinator (MS DTC) transaction failed: 0x8004d00e(XACT_E_NOTRANSACTION). 2024-04-02 14:01:35.11 spid156 Error: 8509, Severity: 16, State: 1. 2024-04-02 14:01:35.11 spid156 Import of Microsoft Distributed Transaction Coordinator (MS DTC) transaction failed: 0x8004d00e(XACT_E_NOTRANSACTION). 2024-04-02 14:02:01.15 spid853 Error: 8509, Severity: 16, State: 1. 2024-04-02 14:02:01.15 spid853 Import of Microsoft Distributed Transaction Coordinator (MS DTC) transaction failed: 0x8004d00e(XACT_E_NOTRANSACTION). 2024-04-02 14:02:35.74 spid35s CImageHelper::Init () Version-specific dbghelp.dll is not used 2024-04-02 14:02:35.74 spid35s Using 'dbghelp.dll' version '4.0.5' 2024-04-02 14:02:35.75 spid35s **Dump thread - spid = 0, EC = 0x0000020BD57C1E10 ..중략.. 2024-04-02 14:02:35.75 spid35s ***Stack Dump being sent to \SQLDump0017.txt 2024-04-02 14:02:35.75 spid35s * ******************************************************************************* 2024-04-02 14:02:35.75 spid35s * 2024-04-02 14:02:35.75 spid35s * BEGIN STACK DUMP: 2024-04-02 14:02:35.75 spid35s * 04/02/24 14:02:35 spid 35 2024-04-02 14:02:35.75 spid35s * 2024-04-02 14:02:35.75 spid35s * Location: "sql\\ntdbms\\hekaton\\engine\\core\\tx.cpp":6337 2024-04-02 14:02:35.75 spid35s * Expression: Dependencies.CommitDepCountOut >= 1 2024-04-02 14:02:35.75 spid35s * SPID: 35 2024-04-02 14:02:35.75 spid35s * Process ID: 5652 2024-04-02 14:03:23.88 spid35s Timeout waiting for external dump process 21796. 2024-04-02 14:03:23.88 spid35s Error: 17066, Severity: 16, State: 1. 2024-04-02 14:03:23.88 spid35s SQL Server Assertion: File: <"sql\\ntdbms\\hekaton\\engine\\core\\tx.cpp">, line=6337 Failed Assertion = 'Dependencies.CommitDepCountOut >= 1'. This error may be timing-related. If the error persists after rerunning the statement, use DBCC CHECKDB to check the database for structural integrity, or restart the server to ensure in-memory data structures are not corrupted. ..중략.. 2024-04-02 14:03:23.88 Server The state of the local availability replica in availability group 'L_AVG' has changed from 'PRIMARY_NORMAL' to 'RESOLVING_NORMAL'. The state changed because the lease between the local availability replica and Windows Server Failover Clustering (WSFC) has expired. For more information, see the SQL Server error log or cluster log. If this is a Windows Server Failover Clustering (WSFC) availability group, you can also see the WSFC management console. 2024-04-02 14:03:23.88 spid189s The availability group database "DATABASE_P03" is changing roles from "PRIMARY" to "RESOLVING" because the mirroring session or availability group failed over due to role synchronization. This is an informational message only. No user action is required. 2024-04-02 14:03:23.88 spid325s The availability group database " DATABASE_03 _IF" is changing roles from "PRIMARY" to "RESOLVING" because the mirroring session or availability group failed over due to role synchronization. This is an informational message only. No user action is required. 2024-04-02 14:03:23.88 spid851s The availability group database " DATABASE_03_HMI_2" is changing roles from "PRIMARY" to "RESOLVING" because the mirroring session or availability group failed over due to role synchronization. This is an informational message only. No user action is required. 2024-04-02 14:03:23.88 spid849s The availability group database " DATABASE_03_P03" is changing roles from "PRIMARY" to "RESOLVING" because the mirroring session or availability group failed over due to role synchronization. This is an informational message only. No user action is required. #ClusterLog 00002c40.00003588::2024/04/02-14:02:40.450 INFO [RES] SQL Server Availability Group: [hadrag] SQL Server component 'system' health state has been changed from 'clean' to 'warning' at 2024-04-02 14:02:40.447 00002c40.00003588::2024/04/02-14:02:40.453 INFO [RES] SQL Server Availability Group: [hadrag] SQL Server component 'query_processing' health state has been changed from 'clean' to 'warning' at 2024-04-02 14:02:40.447 00002c40.00000844::2024/04/02-14:02:57.490 ERR [RES] SQL Server Availability Group <L_AVG>: [hadrag] Lease renewal failed with timeout error 00002c40.00000844::2024/04/02-14:02:57.490 ERR [RES] SQL Server Availability Group <L_AVG>: [hadrag] The lease is expired. The lease should have been renewed by 2024/04/02-12:02:47.490 00002c40.00003858::2024/04/02-14:02:58.046 ERR [RES] SQL Server Availability Group <L_AVG>: [hadrag] Availability Group lease is no longer valid 00002c40.00003858::2024/04/02-14:02:58.046 ERR [RES] SQL Server Availability Group <L_AVG>: [hadrag] Resource Alive result 0. 00002c40.00003858::2024/04/02-14:02:58.046 ERR [RES] SQL Server Availability Group <L_AVG>: [hadrag] Availability Group lease is no longer valid 00002c40.00003858::2024/04/02-14:02:58.046 ERR [RES] SQL Server Availability Group <L_AVG>: [hadrag] Resource Alive result 0. 00002c40.00003858::2024/04/02-14:02:58.046 WARN [RHS] Resource L_AVG IsAlive has indicated failure. 00001cec.00002838::2024/04/02-14:02:58.046 INFO [RCM] HandleMonitorReply: FAILURENOTIFICATION for 'L_AVG', gen(0) result 1/0. 00002c40.00003858::2024/04/02-14:02:58.046 INFO [RHS-WER] Scheduling WER ERROR report in 10.000. ReportId 2f1efff4-5677-4f46-8c8c-9162e4c155db; 00001cec.00002838::2024/04/02-14:02:58.046 INFO [RCM] Res L_AVG: Online -> ProcessingFailure( StateUnknown ) 00001cec.00002838::2024/04/02-14:02:58.046 INFO [RCM] TransitionToState(L_AVG) Online-->ProcessingFailure.
해당 이슈가 Failover를 Trigger하는 부차적인 이슈가 있으며, 이로인한 failover를 반복적으로 수행되나 해당 역할을 Online시키지 못함에 따라 반복적으로 dump로 인한 failover가 수행되었습니다.
이과정에서 large transaction rollback및 반복적인 failover시도로인한 DB연결이슈(983)가 발생한 것으로 확인하였습니다.
2024/04/02-14:03:23.916 INFO [RCM] rcm::RcmApi::MoveGroup: (Group:L_AVG Dest:1 Flags:0 MoveType:MoveType::ManualCur.State:Pending, ContextSize:0) 2024/04/02-14:03:23.917 ERR [RCM] rcm::RcmApi::OnlineResource: (5023)' because of 'The API call is not valid while resource is in the [Terminating to DelayRestartingResource] state.'
2024-04-02 14:03:23.93 spid725s Error: 3624, Severity: 20, State: 1. 2024-04-02 14:03:23.93 spid725s A system assertion check has failed. Check the SQL Server error log for details. Typically, an assertion failure is caused by a software bug or data corruption. To check for database corruption, consider running DBCC CHECKDB. If you agreed to send dumps to Microsoft during setup, a mini dump will be sent to Microsoft. An update might be available from Microsoft in the latest Service Pack or in a Hotfix from Technical Support. 2024-04-02 14:03:23.93 spid725s Error: 3314, Severity: 21, State: 3. 2024-04-02 14:03:23.93 spid725s During undoing of a logged operation in database 'tempdb' (page (1:139) if any), an error occurred at log record ID (17626:408077:603). Typically, the specific failure is logged previously as an error in the operating system error log. Restore the database or file from a backup, or repair the database. ..중략.. 2024-04-02 14:04:22.71 Logon Error: 983, Severity: 14, State: 1. 2024-04-02 14:04:22.71 Logon Unable to access availability database 'DATABASE_P03' because the database replica is not in the PRIMARY or SECONDARY role. Connections to an availability database is permitted only when the database replica is in the PRIMARY or SECONDARY role. Try the operation again later. 2024-04-02 14:04:30.07 spid189s Nonqualified transactions are being rolled back in database DATABASE_P03 for an Always On Availability Groups state change. Estimated rollback completion: 0%. This is an informational message only. No user action is required. 2024-04-02 14:04:32.07 spid189s Nonqualified transactions are being rolled back in database DATABASE_P03 for an Always On Availability Groups state change. Estimated rollback completion: 0%. This is an informational message only. No user action is required. 2024-04-02 14:04:32.99 spid653s Remote harden of transaction 'GhostCleanupTask' (ID 0x00000072638fd8cd 0001:3a728b14) started at Apr 2 2024 2:04PM in database 'DATABASE_P03' at LSN (170966:295662:202) failed. 2024-04-02 14:04:33.67 spid325s Attempting to recover in-doubt distributed transactions involving Microsoft Distributed Transaction Coordinator (MS DTC). This is an informational message only. No user action is required. 2024-04-02 14:04:33.67 spid37s Always On: DebugTraceVarArgs AR '[HADR] [Primary] operation on replicas [5777243E-1C2F-4399-8B8F-8F006F9FD4EE]->[CFF305E1-8C94-4DB3-85D7-0EDD5502E88E], database [DATABASE_P03_IF], remote endpoint [TCP://LES.es.net:5022], source operation [8909B701-63D0-4C65-BE06-CE7BC04DD049]: Transitioning from [CATCHUP] to [COMPLETED].' 2024-04-02 14:04:33.67 spid46s Always On: DebugTraceVarArgs AR '[HADR] [Primary] operation on replicas [5777243E-1C2F-4399-8B8F-8F006F9FD4EE]->[7ED01BC6-97DF-41C4-84E9-737FE70CB40B], database [DATABASE_P03_IF], remote endpoint [TCP://LES.es.net:5022], source operation [79597AD0-EB94-4E28-ACC6-0E791C5BB0E0]: Transitioning from [CATCHUP] to [COMPLETED].' 2024-04-02 14:04:33.67 spid974s [DbMgrPartnerCommitPolicy::SetReplicaInfoInAg] DbMgrPartnerCommitPolicy::SetSyncAndRecoveryPoint: CFF305E1-8C94-4DB3-85D7-0EDD5502E88E:10:4 2024-04-02 14:04:34.07 spid189s Nonqualified transactions are being rolled back in database DATABASE_P03 for an Always On Availability Groups state change. Estimated rollback completion: 0%. This is an informational message only. No user action is required.
이후 고객사에서 LES Server재시작(2024-04-02 14:49)이후 정상적으로 'DATABASE_P03' Online되며 AG가 정상적으로 Online되었습니다.
2024-04-02 14:49:51.76 Server SQL Server is terminating because of a system shutdown. This is an informational message only. No user action is required. 2024-04-02 15:00:39.69 spid46s Always On Availability Groups connection with secondary database established for primary database 'DATABASE_P03' on the availability replica 'LES2' with Replica ID: {cff305e1-8c94-4db3-85d7-0edd5502e88e}. This is an informational message only. No user action is required. 2024-04-02 15:00:39.81 spid139s Always On Availability Groups connection with secondary database established for primary database 'DATABASE_P03' on the availability replica 'LES2' with Replica ID: {cff305e1-8c94-4db3-85d7-0edd5502e88e}. This is an informational message only. No user action is required. 2024-04-02 15:00:52.81 spid79s Always On: DebugTraceVarArgs AR '[HADR] [Primary] operation on replicas [5777243E-1C2F-4399-8B8F-8F006F9FD4EE]->[CFF305E1-8C94-4DB3-85D7-0EDD5502E88E], database [DATABASE_P03], remote endpoint [TCP://LES2.es.net:5022], source operation [719D2611-5566-404F-A02F-B08684AE5A07]: Transitioning from [CATCHUP] to [COMPLETED].' 2024-04-02 15:00:57.02 spid46s [DbMgrPartnerCommitPolicy::SetReplicaInfoInAg] DbMgrPartnerCommitPolicy::SetSyncAndRecoveryPoint: CFF305E1-8C94-4DB3-85D7-0EDD5502E88E:11:4 2024-04-02 15:00:57.02 spid46s DbMgrPartnerCommitPolicy::SetSyncState: CFF305E1-8C94-4DB3-85D7-0EDD5502E88E:11:4
[제안사항]
해당 이슈는 CU21에서 FIX되었으며, 최소 CU21로 patch하시는 것을 제안드립니다.
DECLARE @SERVER_ROLE nvarchar(50)
SELECT
@SERVER_ROLE = A.ROLE_DESC
FROM sys.dm_hadr_availability_replica_states AS A
INNER JOIN sys.availability_groups AS B ON A.GROUP_ID = B.GROUP_ID
WHERE A.IS_LOCAL = 1
IF @SERVER_ROLE = 'PRIMARY'
BEGIN
PRINT ' Go To the next step.'
END
ELSE
BEGIN
RAISERROR ('Do not go to the next step.', 16, 1)
END
-- Description: Turns a query into a formatted HTML table. Useful for emails.
-- Any ORDER BY clause needs to be passed in the separate ORDER BY parameter.
-- =============================================
CREATE PROC [dbo].[spQueryToHtmlTable]
(
@query nvarchar(MAX), --A query to turn into HTML format. It should not include an ORDER BY clause.
@orderBy nvarchar(MAX) = NULL, --An optional ORDER BY clause. It should contain the words 'ORDER BY'.
@html nvarchar(MAX) = NULL OUTPUT --The HTML output of the procedure.
)
AS
BEGIN
SET NOCOUNT ON;
IF @orderBy IS NULL BEGIN
SET @orderBy = ''
END
SET @orderBy = REPLACE(@orderBy, '''', '''''');
DECLARE @realQuery nvarchar(MAX) = '
DECLARE @headerRow nvarchar(MAX);
DECLARE @cols nvarchar(MAX);
SELECT * INTO #dynSql FROM (' + @query + ') sub;
SELECT @cols = COALESCE(@cols + '', '''''''', '', '''') + ''['' + name + ''] AS ''''td''''''
FROM tempdb.sys.columns
WHERE object_id = object_id(''tempdb..#dynSql'')
ORDER BY column_id;
SET @cols = ''SET @html = CAST(( SELECT '' + @cols + '' FROM #dynSql ' + @orderBy + ' FOR XML PATH(''''tr''''), ELEMENTS XSINIL) AS nvarchar(max))''
EXEC sys.sp_executesql @cols, N''@html nvarchar(MAX) OUTPUT'', @html=@html OUTPUT
SELECT @headerRow = COALESCE(@headerRow + '''', '''') + ''<th>'' + name + ''</th>''
FROM tempdb.sys.columns
WHERE object_id = object_id(''tempdb..#dynSql'')
ORDER BY column_id;
SET @headerRow = ''<tr>'' + @headerRow + ''</tr>'';
SET @html = ''<table border="1">'' + @headerRow + @html + ''</table>'';
';
EXEC sys.sp_executesql @realQuery, N'@html nvarchar(MAX) OUTPUT', @html=@html OUTPUT
END
GO
As database administrators, we have to support different SQL Server environments. Often it becomes a challenge and obvious to understand the current server health status. To attain this goal based on my requirements, I have created this small tool just for fun with my limited development application skill. It is completely Free, Agent less, No Installation/Configuration is required, Single executable and portable, easy to use and only needs a couple of clicks to be up and running.
Agreement:
This is a non-commercial, educational and learning purpose tool. It is not an alternative for any commercial grade application. This tool is efficient and sharp like a blade; however, I will not able to provide any warranty, guarantee or accuracy of this tool. Although it is a lightweight data collection and visualization tool, it should not cause any performance issues, however you should test it yourself before running it against any database server.
Figure: SQL Performance Monitor
A challenge: Retrieving and visualizing the SQL Server performance data is always a challenge and a tedious task for SQL Server database professionals. Utilizing the Windows PerfMon application is the easiest way to perform this task as well as querying “sys.dm_os_performance_counters” and some other DMVs brings a lot of useful information. Starting from SQL Server 2005, Microsoft has introduced DMV to query various internal metadata directly to explore various health status data. Although collecting and analyzing SQL Server performance data in a regular basis provides trending ability, monitoring real-time performance data is critical to understand an ongoing performance condition that is occurring.
We are all familiar with built-in “SQL Server Activity Monitor” and obviously it is a good starting point to troubleshoot some SQL Server issues. However, the capacity of this tool is limited as it does not provide other performance metrics which are important to understand the server health status. To extend this idea especially during a performance condition, I have attempted to develop a “SQL Performance Monitor” desktop app by including some other interesting metrics which I believe might be helpful to troubleshoot or understand a problem.
This tool collects more than 50+ performance data directly from SQL Server in real-time and shows data in the chart continuously. Also, it does not require any installation and configuration. Data collection: SQL Scripts used in my tool are excerpted from SSMS and some are collected from various forums which are freely available. My understanding is that all the scripts that I have used are reliable however if any are not working, please let me know and I will attempt to fix the issue. How does it work? 1.Has the ability to monitor only a single SQL instance at a time and can be used against all editions of SQL Server from 2005 to SQL 2014.
2.Charts and grids will be populated with collected performance data every 5 seconds by default (can be changed) for every 5 minutes (can be changed) moving forward.
3.Performance data will be saved automatically as they are collected in a SQLite database (sqlmonitor.db3). 4.All saved performance data can be queried, and then can be exported as a CSV format. As “sqlmonitor.db3” is not protected therefore it can be opened with any SQLite tool. Limitations: 1.It has no notification system, such as email, alert, popup. 2.It is a desktop 32-bit application, cannot run as a service. 3.Chart colors have no special meaning. Known Limitations: (a)SQL 2005 – in the “Server Info” tab the “Available Memory” will be zero. (b)CPU utilization has been calculated from “Resource Pool” and @@CPU_BUSY. Due to the internal limitation of SQL Server, and feature limitation of Standard and Express editions, CPU value may show zero on the chart. In Enterprise edition, CPU utilization will not be zero. How to run:
(a)Create a folder.
(b)Download the “SQLMonitor.exe” in that folder.
(c)Run the executable “SQLMonitor.exe”– that’s it.
(d)There is no extra configuration or components required to run this tool.
Connect to a database server: The tool bar of “SQL Performance Monitor”
Figure#1: Tool bar of SQL Activity Monitor
First time connection: To connect a SQL Server instance, click the “SQL Server to Monitor” button. Supply the required information and then click “Try Connect” in the connection dialog box. Once connected, close the connection dialog box or choose another server to connect to. All charts will be populated for an hour with blank data once a connection is made. It continues to collect and display data based on the duration configured on the tool bar. All collected data will be saved in a SQLite database (sqlmonitor.db) for later review and analysis. Using a saved connection: A successful connection can be saved for later use. Once the tool successfully connects to a database server, click the “save connection” button to save the connection string. An encoded text file will be created in the same folder with the “.txt” extension where the “SQLMonitor.exe” resides. From the bottom list box of the “SQL Server Connection” (figure#2) dialog box, double click a previously saved file to connect to a SQL Server instance. Couple of Screenshots from “SQL Performance Monitor”
Figure#2: SQL Server Connection dialog
Figure#3A: Viewing all running sessions
Figure#3B: Viewing all sessions
Historical data: In the history tab, put “SQL Instance Name” and “date” to query historical data. Click any column header to view data in the chart. All data and charts can be saved. Figure#4: Historical data browse
SELECT
database_name = DB_NAME(database_id)
, log_size_mb = CAST(SUM(CASE WHEN type_desc = 'LOG' THEN size END) * 8. / 1024 AS DECIMAL(8,2))
, row_size_mb = CAST(SUM(CASE WHEN type_desc = 'ROWS' THEN size END) * 8. / 1024 AS DECIMAL(8,2))
, total_size_mb = CAST(SUM(size) * 8. / 1024 AS DECIMAL(8,2))
FROM sys.master_files WITH(NOWAIT)
WHERE database_id = DB_ID() -- for current db
GROUP BY database_id
ALTER FUNCTION [dbo].[GetDBSize]
(
@db_name NVARCHAR(100)
)
RETURNS TABLE
AS
RETURN
SELECT
database_name = DB_NAME(database_id)
, log_size_mb = CAST(SUM(CASE WHEN type_desc = 'LOG' THEN size END) * 8. / 1024 AS DECIMAL(8,2))
, row_size_mb = CAST(SUM(CASE WHEN type_desc = 'ROWS' THEN size END) * 8. / 1024 AS DECIMAL(8,2))
, total_size_mb = CAST(SUM(size) * 8. / 1024 AS DECIMAL(8,2))
FROM sys.master_files WITH(NOWAIT)
WHERE database_id = DB_ID(@db_name)
OR @db_name IS NULL
GROUP BY database_id
IF OBJECT_ID('tempdb.dbo.#space') IS NOT NULL
DROP TABLE #space
CREATE TABLE #space (
database_id INT PRIMARY KEY
, data_used_size DECIMAL(18,2)
, log_used_size DECIMAL(18,2)
)
DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = STUFF((
SELECT '
USE [' + d.name + ']
INSERT INTO #space (database_id, data_used_size, log_used_size)
SELECT
DB_ID()
, SUM(CASE WHEN [type] = 0 THEN space_used END)
, SUM(CASE WHEN [type] = 1 THEN space_used END)
FROM (
SELECT s.[type], space_used = SUM(FILEPROPERTY(s.name, ''SpaceUsed'') * 8. / 1024)
FROM sys.database_files s
GROUP BY s.[type]
) t;'
FROM sys.databases d
WHERE d.[state] = 0
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
EXEC sys.sp_executesql @SQL
SELECT
d.database_id
, d.name
, d.state_desc
, d.recovery_model_desc
, t.total_size
, t.data_size
, s.data_used_size
, t.log_size
, s.log_used_size
, bu.full_last_date
, bu.full_size
, bu.log_last_date
, bu.log_size
FROM (
SELECT
database_id
, log_size = CAST(SUM(CASE WHEN [type] = 1 THEN size END) * 8. / 1024 AS DECIMAL(18,2))
, data_size = CAST(SUM(CASE WHEN [type] = 0 THEN size END) * 8. / 1024 AS DECIMAL(18,2))
, total_size = CAST(SUM(size) * 8. / 1024 AS DECIMAL(18,2))
FROM sys.master_files
GROUP BY database_id
) t
JOIN sys.databases d ON d.database_id = t.database_id
LEFT JOIN #space s ON d.database_id = s.database_id
LEFT JOIN (
SELECT
database_name
, full_last_date = MAX(CASE WHEN [type] = 'D' THEN backup_finish_date END)
, full_size = MAX(CASE WHEN [type] = 'D' THEN backup_size END)
, log_last_date = MAX(CASE WHEN [type] = 'L' THEN backup_finish_date END)
, log_size = MAX(CASE WHEN [type] = 'L' THEN backup_size END)
FROM (
SELECT
s.database_name
, s.[type]
, s.backup_finish_date
, backup_size =
CAST(CASE WHEN s.backup_size = s.compressed_backup_size
THEN s.backup_size
ELSE s.compressed_backup_size
END / 1048576.0 AS DECIMAL(18,2))
, RowNum = ROW_NUMBER() OVER (PARTITION BY s.database_name, s.[type] ORDER BY s.backup_finish_date DESC)
FROM msdb.dbo.backupset s
WHERE s.[type] IN ('D', 'L')
) f
WHERE f.RowNum = 1
GROUP BY f.database_name
) bu ON d.name = bu.database_name
ORDER BY t.total_size DESC
use master
DECLARE @xQry NVARCHAR(MAX)=''
SELECT @xQry+= ' UNION ALL SELECT '''+name+''' COLLATE Modern_Spanish_CI_AS AS [Database],
schema_name(tab.schema_id) + ''.'' + tab.name COLLATE Modern_Spanish_CI_AS AS [table],
cast(sum(spc.used_pages * 8)/1024.00 as numeric(36, 2)) as used_mb,
cast(sum(spc.total_pages * 8)/1024.00 as numeric(36, 2)) as allocated_mb
from '+name+'.sys.tables tab
join '+name+'.sys.indexes ind
on tab.object_id = ind.object_id
join '+name+'.sys.partitions part
on ind.object_id = part.object_id and ind.index_id = part.index_id
join '+name+'.sys.allocation_units spc
on part.partition_id = spc.container_id
group by schema_name(tab.schema_id) + ''.'' + tab.name COLLATE Modern_Spanish_CI_AS'
FROM sys.databases
SET @xQry= RIGHT(@xQry,LEN(@xQry)-11) + ' order by 3 desc'
EXEC (@xQry)