Upload
nigel
View
142
Download
7
Embed Size (px)
DESCRIPTION
ASE 105: The MDA Tables - Finding Out What Goes On Inside ASE. Rob Verschoor Consultant, Sypron B.V. [email protected] Peter Dorfman Senior Staff Software Engineer Sybase, Inc. [email protected]. About us. About Rob consultant for ASE & Replication Server worked with ASE since 1989 - PowerPoint PPT Presentation
Citation preview
ASE 105: The MDA Tables - Finding Out What Goes On Inside ASE
Rob VerschoorConsultant, Sypron B.V.
Peter DorfmanSenior Staff Software Engineer
Sybase, [email protected]
2
About Rob consultant for ASE & Replication Server worked with ASE since 1989 based in The Netherlands
www.sypron.nl
Published three books about Sybase:
“The Complete Sybase Replication Server Quick Reference Guide” (new)
"The Complete Sybase ASE Quick Reference Guide” (3rd edition, new)
"Tips, Tricks & Recipes for Sybase ASE"
About us
3
About Peter 11+ years at Sybase ASE Engineering Designed and developed system management, monitoring and diagnostic
tools for the ASE Leads the design and development of system management features for the
ASE and other Sybase database products
About us
4
Quick introduction to MDA tables Possible applications of MDA tables
What’s that application doing? Diagnosing bottlenecks Identifying unused indexes Identifying ‘hot’ tables
Historical MDA tables Archiving historical MDA table data Performance impact of MDA tables Counter wrap Analyzing stored procedure activity Miscellaneous topics
Topics
5
MDA tables were introduced in ASE 12.5.0.3 MDA = Monitoring and Diagnostic Access also called “monitoring tables”
35 proxy tables in ‘master’ database monSysSQLText, monObjectActivity, monCachedObject (etc.) can be accessed with regular SQL statements when queried, tables are created on-the-fly from memory structures no data is stored in master database
Must be installed: ‘installmontables’ script
No license needed: included in ASE base product
Only small performance impact on ASE (<5%)
Quick introduction to MDA tables
6
MDA tables provide access to low-level monitoring data resource usage in ASE per table/query/entire server current activity in ASE per spid/query/procedure/table recent activity: recently completed statements, with the resources they
required
Some examples of practically relevant information: amount of memory occupied in the data cache by each table or index most frequently used tables/procedures top-N queries for CPU, I/O, elapsed time,... find unused indexes SQL text of currently executing/recently executed statements automatically kill user processes that have been idle for more than X minutes provide server status information even when tempdb is full
Quick introduction to MDA tables
7
Interesting Facts about MDA Tables
MDA table data does not take up disk space Data is generated on-the-fly when an MDA table is queried
Exception: Historical table data is stored in ASE memory
Queries on MDA tables cause a second connection to the server sysprocesses.program_name = OmniServer-# # is the SPID for the process that ran query on MDA table E.g., OmniServer-56
Some MDA table data is shared with sp_sysmon and Monitor Server These columns will be cleared if sp_sysmon clears counters
8
For more MDA basics, and a brief discussion of all tables: see Rob’s presentation from Techwave 2003 (www.sypron.nl/mda)
In this presentation: we want to go one step further than just the basics look at practical applications of MDA tables things that are useful for you as a DBA
Quick introduction to MDA tables
9
Possible applications of MDA tables
10
Does this sound familiar? a third-party ‘black box’ application runs on your ASE server you have the feeling it sometime slows down the entire server... … but you don’t know which queries it is sending to ASE
Classic solutions: use “cmdtext” auditing to intercept the application’s T-SQL commands use traceflag 11202 (writes all incoming client language to the errorlog) use third-party tools to find T-SQL commands by intercepting network packets dbcc sqltext()
…but all these methods have significant limitations or drawbacks
What’s that application doing?
11
Solution: MDA tables monProcessSQLText & monSysSQLText
monProcessSQLText: currently executing SQL
monSysSQLText: recently executed SQL, now completed Historical table Lets you “look back” in time By copying rows regularly into an ‘archive’ table, complete history can be
preserved
What’s that application doing?
12
Also handy for RepServer DBAs: Quick way to figure out exactly which SQL is executed against your replicate DB Especially handy when developing/debugging custom function strings You can look for specific statements only:
select SQLText from master..monSysSQLText
where SQLText like “%MyTable%”
What’s that application doing?
13
Performance tuning is all about finding bottlenecks There’s no point in optimizing something that isn’t a bottleneck
Historically, it’s been difficult to diagnose bottlenecks in ASE sp_sysmon provides some info about some aspects of resource usage... … but interpretation is still difficult … and sort-of requires having eliminated application-level bottlenecks first
MDA tables offer a new angle on bottlenecks: wait event info MDA tables: monProcessWaits, monSysWaits Contain wait times for ~300 different internal wait events (monWaitEventInfo) monSysWaits: for entire ASE server monProcessWaits: for currently active spids Wait times are cumulative and universally increasing
Diagnosing bottlenecks
14
Here’s the idea: When something is a bottleneck, someone in ASE is waiting for it By looking at the distribution of wait times during an interval, a bottleneck
might be identified
One extreme: the server is completely quiet All spids are waiting for input from the network
Other extreme: the server is perfectly, fully utilised spids are mostly being scheduled around to do real work
When a bottleneck exists: You’d expect to see wait time peaks for certain events
Diagnosing bottlenecks
15
Tool: stored procedure ‘sp_mda_wait’ Samples current wait time counters Waits for a certain interval Samples wait time counters again Calculates and reports differences (delta values)
sp_mda_wait { 'server' | '<spid_no>' | 'all' } [, 'hh:mm:ss' [, top_N ]
Defaults: interval: 10 seconds top_N = 20
Procedure can be downloaded from www.sypron.nl/mda
Diagnosing bottlenecks
16
Example: A session is performing continuous insert/delete cycles The top wait events for this specific spid:
WaitSecs NrWaits WaitEvent WaitEventID
-------- ------- ----------------------------------- -----------
8 140 waiting for disk write to complete 51
1 140 waiting for disk write to complete 55
0 140 waiting on run queue after yield 214
0 3 wait for buffer read to complete 29
Diagnosing bottlenecks
17
Example: A session is performing continuous insert/delete cycles The top wait events for the entire ASE server:
WaitSecs NrWaits WaitEvent -------- ------- --------------------------------------------- 79 6 hk: pause for some time 60 1 xact coord: pause during idle loop 53 1 checkpoint process idle loop 10 3 waiting while no network read or write is req 10 3 waiting for incoming network data 10 1 waiting for date or time in waitfor command 9 55 waiting for disk write to complete 1 44 waiting for disk write to complete 1 22 wait for buffer write to complete 0 187 waiting on run queue after sleep 0 62 waiting on run queue after yield
0 24 waiting for CTLIB event to complete
Diagnosing bottlenecks
18
Example: A session is performing continuous insert/delete cycles
9 55 waiting for disk write to complete 1 44 waiting for disk write to complete
1 22 wait for buffer write to complete
Conclusion: The bottleneck for this particular spid is disk writes This is not a bottleneck for the server as a whole
Diagnosing bottlenecks
19
Example: A session is performing continuous select count(*) on a small table The top wait events for this specific spid, and for the entire server:
WaitSecs NrWaits WaitEvent-------- ------- ------------------------------------ 0 26 waiting for network send to complete
WaitSecs NrWaits WaitEvent -------- ------- ------------------------------------------------- 314 18 waiting on run queue after yield 221 2519 waiting on run queue after sleep 132 1222 waiting while no network read or write is required 122 24 waiting for CTLIB event to complete 120 2 xact coord: pause during idle loop 79 6 hk: pause for some time 77 9 waiting for incoming network data
Diagnosing bottlenecks
20
Example: A session is performing continuous select count(*) on a small table
Conclusion: the bottleneck for this particular spid is sending the query results to the
client this is not a bottleneck for the server as a whole
Diagnosing bottlenecks
21
Example: No session is doing anything at all The top wait events for an idle spid, and for the entire server are all waiting for incoming
client queries
WaitSecs NrWaits WaitEvent-------- ------- ------------------------------------ 10 0 waiting for incoming network data
WaitSecs NrWaits WaitEvent-------- ------- -------------------------------------------------- 10 3 waiting while no network read or write is required 10 3 waiting for incoming network data 10 2 hk: pause for some time 10 1 waiting for date or time in waitfor command 0 39 waiting on run queue after sleep 0 24 waiting for CTLIB event to complete 0 8 waiting on run queue after yield
Diagnosing bottlenecks
22
sp_mda_wait ‘all’ : print details for all sessions
19 sa AWAITING COMMAND recv sleep VIRGO isql 10 / 0: waiting for incoming network data (250)
21 sa AWAITING COMMAND recv sleep X1252 OmniServer-37
10 / 3: waiting for incoming network data (250)
22 sa INSERT sleeping VIRGO isql
Proc: my_db..my_proc Line# in proc:11
SQL batch: my_proc
4 / 644: waiting for disk write to complete (51)
4 / 776: wait for buffer write to complete (31)
2 / 639: waiting for disk write to complete (55)
0 / 639: waiting on run queue after yield (214)
[...]
Diagnosing bottlenecks
23
[...]
23 sa AWAITING COMMAND recv sleep virgo SC_ASEJ_Mgmt
10 / 0: waiting for incoming network data (250)
26 sa INSERT sleeping sqsh
Proc: my_db..p_bigreport Line# in proc: 116
SQL batch: p_bigreport '20040101', '20040630'
9 / 1: waiting for incoming network data (250)
1 / 640: wait for buffer read to complete (29)
0 / 3: waiting on run queue after yield (214)
0 / 2: wait for buffer write to complete (31)
0 / 2: wait for mass to stop changing (36)
0 / 2: waiting for disk write to complete (51)
0 / 2: waiting for disk write to complete (55)
0 / 2: waiting for network send to complete (251)
[...]
Diagnosing bottlenecks
24
[...]
29 sa LOG SUSPEND sleeping sqsh Line# in batch: 1
SQL batch: insert my_tab values (’test...')
10 / 0: waiting until last chance threshold is cleared (259)
31 sa WAITFOR alarm sleep sqsh Line# in batch: 2
SQL batch: insert t values ('test 1...')
waitfor delay '00:00:30'
insert t v
10 / 0: waiting for date or time in waitfor command (260)
Diagnosing bottlenecks
25
Monitoring Index Utilization
Have you ever wanted to see Which indexes are never used? How frequently they are used? How many inserts, deletes, updates, physical or logical I/O they incur?
monOpenObjectActivity table provides: Table usage count Index usage count Last used dates Physical, logical I/O Row-level insert/delete/update counts Lock wait counts for tables and indexes
NOTE: Statistics are reset when server is booted or object descriptor is reused in memory.
26
Monitoring Index Utilization
select "Database" = db_name(DBID), "Table" = object_name(ObjectID, DBID), IndID = IndexID, UsedCount, LastUsedDate, OptSelectCount, LastOptSelectDate from master..monOpenObjectActivityorder by UsedCount
Table andIndex Usage•Counts•Dates
monOpenObjectActivity
27
Monitoring Table Usage
select "Database" = db_name(DBID), "Table" = object_name(ObjectID, DBID), IndexID, RowsInserted, RowsDeleted, RowsUpdated, LockWaitsfrom monOpenObjectActivityorder by RowsInserted desc
Per Table•Inserts•Deletes•Updates•Lock Waits
monOpenObjectActivity
28
It’s interesting to know which tables and indexes are most frequently used
select * into #t
from master..monOpenObjectActivity
go
select TableName = object_name(ObjectID, DBID), IndexID, LogicalReads, PhysicalReads, Operations, LockWaits
from #t
order by 1, 2
go
Identifying ‘hot’ tables
29
TableName IndexID LogReads PhysReads Operations LockWaits
------------------------------ ------- -------- --------- ---------- ---------
#t___________00000280002095330 0 11517 0 3460 0
#t2__________00000220014256057 0 5 0 5 0
cust_tab 0 12315 0 17 2
cust_tab 2 239 0 0 0
products_tb 0 282294 9043 609 97
products_tb 2 36450 0 0 0
Identifying ‘hot’ tables
30
Understanding and Using
Historical Tables
31
Using Historical Tables
Which MDA tables are “historical” tables? What are Historical Tables? How do they work? What is the correct size to configure them? Archiving historical table data Tips on using historical tables
32
Which Tables are Historical Tables?
monSysSQLText Records every SQL command executed on the server
monSysPlanText Records the Query Plan for every SQL command executed on the server
monSysStatement Reports the statistics for every statement within every query, batch, stored
procedure, trigger, etc. executed on the server
monErrorLog Records every row written to the server errorlog
monDeadLock Records information on every deadlock that occurs on the server
33
What are Historical Tables?
The historical MDA tables contain a record of “events” within the ASE
E.g., SQL submitted for a query, a statement executed within a batch, error message added to the errorlog
The data for these tables is stored in memory in fixed-sized arrays Size is configurable using sp_configure
Data in Historical tables is transient The arrays are managed as “ring buffers”: After the last entry in the array is written the
first entry will be overwritten
Historical tables are “stateful.” The ASE remembers which records a process has already seen Subsequent queries on same table will return only new records
Why are they stateful? This allows applications to accurately collect or “drain” the rows in these tables without
finding duplicates.
34
Queries on Historical Tables
“Select * from monSysSQLText”
Row 1
Row 3
Row 4
Row 5
Row 6
Row 7
Row 8
Row 2
8:27 AMUser 2:
Never queried table before. Will see
all rows. 8:30 AMUser 1:
Second query willreturn only rows added since last query (5 – 8).
The ASE maintains the connection’s currency in the MDA tableCurrency is reset for each new connection
8:24 AMUser 1:
First query returns rows1 - 4.
8:22 AM: rows 1 – 4Are inserted…
8:26 AM: rows 5 - 8Are inserted…
35
Setting the Size of Historical Tables
These sp_configure parameters determine the number of rows in the historical tables – values are per-engine
errorlog pipe max messages plan text pipe max messages sql text pipe max messages statement pipe max messages deadlock pipe max messages
The value of the parameter is the number of rows per engine Correct size depends on
Rate at which rows are written to table Frequency with which queries will be run against the table
For example: 2 engines 5000 rows per minute per engine Select * from monSysStatement every 5 minutes Statement pipe max messages should be greater than or equal to 25000 Result set size??? (50000 rows!)
Errorlog and deadlock pipes are usually much smaller than plan text, sql text and statement pipes
Rate x Frequency = SizeE.g.: 5000/min x 5 min = 25000
Reasonable size on busy system??Could be >> 100000
36
Memory Used by Historical Tables
The following sizes are approximate: monSysStatement
90 bytes/row monSysSQLText
273 bytes/row 255 bytes SQL Text per row
monErrorLog 542 bytes/row
monDeadLock 517 bytes/row
monSysPlanText 194 bytes/row
Also note the max SQL text monitored configuration option Allocates memory per process (the only MDA-related config option that’s static) Determines maximum size of a SQL batch to capture Does not effect size of SQL Text Pipe rows
37
Tips on Using Historical Tables
Do not use in subqueries or joins Save contents of tables to an archive table or database for
analysis When collecting long-term data, archive data on a regular
basis and size tables to avoid data loss How do you know whether the table for the buffer has
wrapped? If # of rows returned == size of buffer * # of engines In other words, if you get the entire size of the buffer, some rows were
probably lost Currently, it is not possible to determine how many rows were lost
38
Quick way of removing all contents of a history table:
exec(“select * into #t from master..monSysSQLText”)
Resets process’s currency in the historical table pipe Handy when:
you’re not interested in the history you want to do a quick test you’ve configured “sql text pipe max messages” to 2000
See how it works? select…into #t saves you from waiting until 2000 lines have been flushed to your
window exec() drops #t automatically, so you don’t have to
Tips on Using Historical Tables
39
Archiving Historical Table Data
40
Archiving Historical Table Data
Because data in historical tables is transient Because repeated queries on historical tables will not return the
same rows Even in subqueries or joins!
Data from historical tables should be moved to permanent or temporary archive storage for analysis
Example: select * into #tempStatement from master..monSysStatementinsert #tempStatement select * from master..monSysStatement
41
For a ‘complete’ picture of what happened inside ASE: ‘regularly’ copy historical MDA tables to permanent tables
If copied too infrequently: data is pushed out of the pipe before it was retrieved
If copied too frequently (e.g. every second): cause additional workload on the ASE server
Archiving Historical Table Data
42
A possible approach: a ‘collector’ stored proc which frequently extracts data from the MDA tables
‘sp_mda_collect‘
uses a separate database to collect the historical data in permanent tables
the permanent tables have the same layout as the historical MDA tables
added a composite unique index with ignore_dup_key on key columns (SPID, KPID, etc.) to filter out duplicates (in case the proc needs to be restarted…)
Archiving Historical Table Data
43
sp_mda_collect
sp_mda_collect ‘start’ [, ‘hh:mm:ss’ ] -- runs in a loop (default interval = 30 sec.)
sp_mda_collect ‘stop’ -- run from a different session, stops the original procedure
sp_mda_collect ‘status’ -- displays #rows saved in archive tables
Procedure can be downloaded from www.sypron.nl/mda
Archiving Historical Table Data
44
Enterprise Monitoring Repository and Center
To access MDA tables from a remote server Create the MDA proxy tables on a central server Map MDA proxy tables to each monitored server
Reduces load on monitored ASE servers Provides central source of monitoring data for your
enterprise Allows easy archiving of enterprise data to permanent
storage in database on repository server
45
Creating an Enterprise Monitoring Center
Create monitoring database on central server Copy and edit installmontables script
Two options:• Create separate monitoring database for each monitored
server• Add server name to MDA table names to create unique
table names for each server within a single database Set the use database command to use the correct database Change the “loopback” server name to the remote server name of
the monitored server in your central server
46
Modifying installmontables Script
……use monitor_svrtest1go……
create existing table monProcedureCache (
Requests int,Loads int,Writes int,Stalls int,
) external procedure at “svrtest1...$monProcedureCache"go
•Creating MDA proxy tables in a separate database for each monitored server
Use a separate database for eachMonitored server
Proxy table points to monitoredserver
47
Modifying installmontables Script
•Creating MDA proxy tables in a single database for all monitored server
……use monitordbgo……
create existing table monProcedureCache_svrtest1 (
Requests int,Loads int,Writes int,Stalls int,
) external procedure at “svrtest1...$monProcedureCache"go
Database in which all proxy tablesWill be created
Unique table name constructed by aAppending server name
Proxy table points to monitoredserver
48
Enterprise Repository: Some Options
Use Rob’s sp_mda_collect stored procedure to collect data from all monitored servers into a central repository database
Create views in your proxy database that add server name or data-time stamp to monitoring data
Use this to store data from multiple server in a single permanent repository table Create a union view to monitor errorlogs across enterprise
create view enterprise_errorlogas select Server = ‘SVROPS', SPID, KPID, FamilyID, EngineNumber, ErrorNumber, Severity, State, Time, ErrorMessagefrom monitor_SVROPS1..monErrorLogUNION select Server = ‘SVRDEV1', SPID, KPID, FamilyID, EngineNumber, ErrorNumber, Severity, State, Time, ErrorMessagefrom monitor_SVRDEV1..monErrorLog
49
Enterprise Errorlog Example
1> select * from enterprise_errorlog where Severity >= 162> go Server SPID KPID FamilyID EngineNumber ErrorNumber Severity State Time ErrorMessage---------- --------- ---------------- ------------- --------
SVROPS1 768 1358430508 768 0 1608 18 4 Jul 28 2004 2:39PM A client process exited abnormally, or a network error was encountered.
Unless other errors occurred, continue processing normally.
50
Enterprise Monitoring Views: Considerations
Queries using UNION in view will fail if any member server is not available
Error 11216 may occur due to broken network connection between local and remote server
Consider creating a stored procedure to iterate over all remote servers
Store data in a temporary table Catch query failures on unavailable servers and continue processing
51
Performance Impact of MDA Tables
52
Performance Impact of MDA Tables
Two questions Impact of data collection? Impact of querying MDA tables?
General performance impact: 5% or less Depends on a number of factors
Configuration of server (e.g., number of engines, memory size, processor speed)
Load on server Configuration of Monitoring parameters
Different monitoring configuration settings have different performance impacts
Fully enabling all options will have greatest impact
53
Performance Impact: Configuration Settings
Lowest impact: Enable monitoring with no other options Tables enabled: monEngine, monDataCache, monProcedureCache,
monOpenDatabases, monSysWorkerThread, monNetworkIO, monLocks, monCachePool, monIOQueue, monDeviceIO, monProcessWorkerThread, monProcessNetIO
Wait Event Timing Plan Text, SQL Text, ErrorLog, DeadlLock
Greatest impact: Per Object Statistics
• monOpenObjectActivity, monProcessObject, monProcessActivity Statement Historical table and Process Statements
• monSysStatement, monProcessStatement• statement pipe active• statement statistics active
54
Performance Impact
Querying MDA tables uses ASE server resources just like any other query
MDA table access does not require disk I/O
First query on MDA table generates a new connection to ASE Shows up as application OmniServer-# (e.g., OmniServer-31) This involves the login process and can take time on a busy system
Queries on large historical Tables, or on monCachedObject with a large cache, could take a long time
55
Performance Impact
Some tables use spinlocks to synchronize data access and can affect queries executing on other engines
Spinlocks are widely used in ASE to synchronize query execution and protect data
Incrementing the MDA counters is not spinlock-protected Would cost too much overhead Risks loosing only an occasional counter increment Reading from the non-historical MDA tables is spinlock-protected
56
Understanding and Handling
Counter Wrap
57
Handling Counter Wrap
What do we mean by “counter wrap”? Why does this happen? Is counter wrap a problem? How can you handle this? Which tables are affected?
58
What is Counter Wrap?
All MDA counter columns are 32-bit signed integers Maximum value is 2147483647
When signed integers are incremented above maximum value they become negative
2147483647 + 1 => - 2147483646
Internal adjustments prevent MDA counter values from becoming negative
Therefore counter ranges are from 0 to 2147483647
When the ASE increments an MDA counter past the maximum value it will return to 0 and start increasing again
59
Does Counter Wrap Mean Data is Lost?
It depends…. If your application is counting total cumulative values (e.g., cache
searches or disk IO) Your application must count the number of times a counter wraps
Multiply wrap count x 2147483647
Is this a good idea? Not usually!
It’s difficult to maintain an accurate wrap count Total cumulative values are not often useful
The alternative: Use delta values instead As long as change in counter values is <= 2147483647, delta values
will be accurate
60
Using Delta Values
What is a delta value? The change in the value of a counter between two points in time
Calculate deltas by subtracting the earlier value from the later value
Select CacheName,
CacheSearches = (e.CacheSearches – s.CacheSearches)
From #cacheStart s, #cacheEnd e
Where s.CacheID = e.CacheID
What if the counter has wrapped since #cacheStart was created??
61
Handling Counter Wrap with Delta Values
If counter has wrapped, add difference between start value and maximum value + 1 to the current value of the counter
Select CacheName, CacheSearches = case when e.CacheSearches < s.CacheSeaches then (2147483648 - s.CacheSearches) + e.CacheSearches) else (e.CacheSearches – s.CacheSearches)endfrom #cacheStart s, #cacheEnd ewhere s.CacheID = e.CacheID
Again: As long as change in counter values is <= 2147483647, delta values will be accurate
62
Is Counter Wrap a Problem?
Most of the time, the question is not “How much?” Usually the question is “Since when?” In other words, we usually analyze rates over a specific time
period. E.g.,
Cache hit ratio over past 5 minutes Rate of network IO per hour Average rate of physical IO’s
These values involve start and end values divide aggregated over a time period - i.e., deltas
63
Which MDA Table Columns Can Wrap?
Not all MDA columns are likely to wrap Some counter values increment slowly Some numeric columns are not counters
Columns that can wrap pretty quickly monDataCache
CacheSearchesLogicalReads
monNetworkIOBytesSentBytesReceived
monSysWaitsWaits
Others wrap less quickly monEngine.ContextSwitches monNetworkIO.PacketsSent
64
Analyzing Stored Procedure Performance
65
Analyzing Stored Procedure Performance
Historical Server provides stored procedure performance information
MDA tables do not provide a table with historical stored procedure statistics
The monSysStatement table can be used to report this information
select ProcName = isnull(object_name(ProcedureID, DBID), "UNKNOWN"),
DBName = isnull(db_name(DBID), "UNKNOWN"),
ElapsedTime = datediff(ms, min(StartTime), max(EndTime))
from master..monSysStatement
group by SPID, DBID, ProcedureID, BatchID
having ProcedureID != 0
66
Stored Procedure Statistics
1> select ProcName = isnull(object_name(ProcedureID, DBID), "UNKNOWN"),2> DBName = isnull(db_name(DBID), "UNKNOWN"),3> ElapsedTime = datediff(ms, min(StartTime), max(EndTime))4> from master..monSysStatement5> group by SPID, DBID, ProcedureID, BatchID6> having ProcedureID != 07> order by 38> go ProcName DBName ElapsedTime ------------------------------ ------------------------------ ----------- p_sybbugstatus engcomdb 1096 sybrev_fetch_revstatus engcomdb 983 p_sybbugstatus engcomdb 923 p_sybbugstatus engcomdb 836 p_sybbugstatus engcomdb 683 p_sybbugstatus engcomdb 620 p_sybbugstatus engcomdb 586 p_sybbugstatus engcomdb 543 p_sybbugstatus engcomdb 533 p_sybbugstatus engcomdb 526….….
67
Sample Stored Procedure Statistics
1> select ProcName = isnull(object_name(ProcedureID, DBID), "UNKNOWN"),2> DBName = isnull(db_name(DBID), "UNKNOWN"),3> ElapsedTime = datediff(ms, min(StartTime), max(EndTime))4> from master..monSysStatement5> group by SPID, DBID, ProcedureID, BatchID6> having ProcedureID != 07> go ProcName DBName ElapsedTime ------------------------------ ------------------------------ ----------- sp_configure master 1000 sp_configure master 3000 sp_configure master 4000 sp_monitor_server sybsystemprocs 0 sp_monitor sybsystemprocs 1000 sp_monitor sybsystemprocs 1000 sp_do_poolconfig sybsystemprocs 0 sp_poolconfig sybsystemprocs 1000 sp_poolconfig sybsystemprocs 0 sp_poolconfig sybsystemprocs 0 sp_helpdb sybsystemprocs 1000
CR# 345056Fixed in
ASE 12.5.1
68
Stored Procedure Performance Averages
Aggregate performance statistics can be derived from the output of the previous query/*** Build a detail table*/select ProcName = isnull(object_name(ProcedureID, DBID), "UNKNOWN"), DBName = isnull(db_name(DBID), "UNKNOWN"), ElapsedTime = datediff(ms, min(StartTime), max(EndTime))into #t1from master..monSysStatementgroup by SPID, DBID, ProcedureID, BatchIDhaving ProcedureID != 0
/*** Calculate aggregate values*/select ProcName, DBName, "Avg" = avg(ElapsedTime), NumExecs = count(*)from #t1group by ProcName, DBNameorder by 3 desc
69
Stored Procedure Performance Averages
1> select ProcName, DBName, "AvgElapsed" = avg(ElapsedTime),2> NumExecs = count(*)3> from #t14> group by ProcName, DBName5> order by 3 desc6> go ProcName Database AvgElapsed NumExecs ------------------------------ ------------ ----------- ----------- p_sybbugstatus engcomdb 483 32 sn_temp_filters_qts1 qts_db 330 26 sy_resolution_insert qts_db 260 44 p_sybbugreleasematrix engcomdb 186 21 create_sn_subscriptions qts_db 108 9 p_sybbugsrelease engcomdb 91 37 sn_temp_filters_qts2 qts_db 83 2 sn_temp_filters_qts4 qts_db 73 11 sn_get_next_key qts_db 69 5 create_sn_filters qts_db 65 5 ……
70
Identifying Poorly Performing Statements
Identify statements within stored procedures consuming greatest CPU time• ProcedureID != 0
/*** Build work table*/select ProcName = isnull(object_name(ProcedureID, DBID), "UNKNOWN"), DBName = convert(char(15), isnull(db_name(DBID), "UNKNOWN")), LineNumber, ElapsedTime = datediff(ms, StartTime, EndTime)into #t1from master..monSysStatementwhere ProcedureID != 0/*** Calculate aggregate values*/select ProcName, DBName, LineNumber, "AvgElapsed" = avg(ElapsedTime)from #t1group by DBName, ProcName, LineNumberhaving avg(ElapsedTime) > (select avg(ElapsedTime) from #t1)order by 4 desc
71
Statements with > Average CPU Time
…… ProcName DBName LineNumber AvgElapsed ------------------------------ --------------- ----------- ----------- row_update qts_db 614 2160 p_sybbugstatus engcomdb 60 240 row_update qts_db 147 98 row_insert qts_db 308 98 e2_CiMember qts_db 71 77 p_sybbugstatus engcomdb 56 76 sy_addl_case_update qts_db 138 70 p_sybbugstatus engcomdb 125 69 sybrev_report_newcrs engcomdb 48 30 log_activity qts_db 155 18 p_sybbugstatus engcomdb 29 16 p_sybbugstatus engcomdb 145 15 log_activity qts_db 90 14
….….
72
Most Frequently Used Stored Procedures
1> select * into #t1 from master..monSysStatement2> go1> select ProcedureName = isnull(object_name(ProcedureID, DBID), "UNKNOWN"),2> "Database" = db_name(DBID),3> "Execs" = count(*)4> from #t15> where ProcedureID != 06> group by DBID, ProcedureID7> order by 3 desc8> go ProcedureName Database Execs ------------------------------ ------------------------------ ----------- sp_mda sybsystemprocs 8138 p_sybbugstatus engcomdb 888 sp_help_rep_agent sybsystemprocs 462 p_sybbugsrelease engcomdb 205 sn_get_next_key qts_db 176 create_sn_filter_criteria qts_db 162 create_sn_subscriptions qts_db 136 create_sn_filters qts_db 120 ….….
73
Measuring time: Be Aware!
Important: CPU Time vs. Elapsed Time Many rows in monSysStatement will have a zero value for CpuTime
and same value for StartTime and EndTime ASE clock granularity is 3 milliseconds Statements or queries that complete in less than 3 ms will usually
report zero CPU time Is this a problem? Yes, if you want to see absolute times for each statement and query No, if you are looking for poorly performing queries or resource
hogs Statements/procedures < 3 milliseconds are probably not a problem
Relative values for normal ranges still useful for detecting significant deviations in performance or resource hogs
74
Stored Procedure Statistics: Suggestions
Do not query monSysStatement directly Build a performance repository Copy contents of monSysStatement to a work table or
permanent table Retain detail data in your repository
Aggregate metrics can always be derived Quantity of data may be a problem
Stored procedures can be analyzed at these levels: Aggregate (max, min, average) Detail – individual execution Statement within stored procedures
sp_monitor “procedure” introduced in ASE 12.5.2 Provides stored procedure details and averages
75
Procedure Cache Tuning
Determine Procedure Cache Hit Ratio
1> select Requests, Loads,
2> "Ratio" = convert(numeric(5,2),(100 - (100 * ((1.0 * Loads)/ Requests))))
3> from monProcedureCache
4> go
Requests Loads Ratio
----------- ----------- --------
7907781 212585 97.31
(1 row affected)
Find most frequently used (“hot”) procedures See previous slide
Determine procedure cache size and utilization
76
Analyzing Procedure Cache Usage
Determine Procedure Cache size and utilization
1> sp_monitorconfig 'procedure cache size'
2> go
Usage information at date and time: Jul 29 2004 8:03AM.
Name Num_free Num_active Pct_act Max_Used
Num_Reuse
------------------------- ----------- ----------- ------- -----------
-----------
procedure cache size 102311 89 0.09 27590
134
Procedure cache hit ratio is high (~97%) Procedure cache not fully utilized (27K of 102K) May make sense to decrease Procedure Cache size
77
Miscellaneous topics
78
Using MDA Tables and sp_sysmon
Monitor Counters are a set of counters used by sp_sysmon and Monitor Server
Some MDA table columns are derived from Monitor Counters sp_sysmon resets the value of Monitor Counters when it
starts This can have an impact on applications using MDA tables or
Monitor Server MDA table columns that come from Monitor Counters are
documented. Attributes column = “counter, reset”
Impact on delta calculations is transient Solutions:
Be careful when using MDA tables and sp_sysmon together Use version of sp_sysmon that does not reset counters (*available soon!)
79
Subqueries, Joins and Self-Joins
Rule of thumb: Don’t use joins or subqueries when querying the MDA tables
There are cases when this rule does not apply Why? Because the MDA table data is transient and reflects
the ASE’s instantaneous state, joins and subqueries may not give the expected result.
Sequential queries on same table can give different results Because of the currency mechanism, self-joins or subqueries
involving one of the historical tables more than once will not work.
Currency is reset by first query and the same rows will not be seen by the subquery or inner join table
Solution: Copy MDA table data to a work table or permanent repository when complex analysis is required.
80
360 columns in 12.5.0.3 (first version of MDA tables)
5 new columns in 12.5.1 monErrorLog.State - state of error monOpenDatabases.QuiesceTag - tag specified with quiesce database (if any) monOpenDatabases.SuspendedProcesses - number of currently suspended
processes due to log-full condition in this database monProcessWorkerThread.FamilyID - spid of parent process monProcessWorkerThread.ParallelQueries - total # parallel queries attempted
Enhancements in 12.5.1
81
2 new columns in 12.5.2 monProcessObject.TableSize - table size in Kb monProcessActivity.WorkTables - total number of work tables created by
the process
Fixes: milliseconds fixed in monSysStatement.StartTime / EndTime can determine be used to determine the exact duration of each statement
(resolution = 3 milliseconds)
Enhancements in 12.5.2
82
Have you used MDA tables?
For which purposes?
Did you write any custom tools/SQL code?
What kind of features/tools would you require to make MDA tables more useful to you?
Can we have your opinion please ?