Difference between revisions of "Finding missing statistics"
Line 1: | Line 1: | ||
− | ASE 15 requires a lot more statistical information to make an optimal queryplan. | + | ASE 15 requires a lot more statistical information to make an optimal queryplan. In ASE 12 it was sufficient to run "update index statistics" on all tables but now also other columns in a query need up to date statistics. |
+ | There are two known methods available. | ||
+ | |||
+ | ==ASE 15.0.3 ESD 1 or later== | ||
+ | |||
+ | ===Configure the server to capture missing statistics=== | ||
+ | sp_configure "capture missing statistics",1 | ||
+ | go | ||
+ | |||
+ | This configuration option will store all missing statistical info into the sysstatistics system table, per database. On a regular basis you can query this table and generate statistics. | ||
+ | Missing statistics can be found through formatid, it will have a value of 110. Each time a missing statistic has been detected it is recorded in the sysstatistics table and the column c0 contains a running total for each miss. Column c0 records this as a hexadecimal value, wrapping at 0xffff to x00000. | ||
+ | |||
+ | ===Sample query for sysstatistics=== | ||
+ | set flushmessage on | ||
+ | set nocount on | ||
+ | go | ||
+ | |||
+ | declare c2 cursor for | ||
+ | select distinct user_name(so.uid),so.name,so.id,st.colidarray | ||
+ | from sysobjects so, sysstatistics st | ||
+ | where so.type = "U" -- User tables | ||
+ | and not (so.sysstat2 & 1024 = 1024 or -- Remote | ||
+ | so.sysstat2 & 2048 = 2048) -- Proxy | ||
+ | and st.id = so.id | ||
+ | and st.formatid = 110 -- Missing | ||
+ | order by 1,2 | ||
+ | go | ||
+ | |||
+ | exec sp_flushstats | ||
+ | go | ||
+ | |||
+ | declare @colid varbinary(2), | ||
+ | @colidarray varbinary(100), | ||
+ | @colnum tinyint, | ||
+ | @colstring varchar(1024), | ||
+ | @table_id int, | ||
+ | @table_name varchar(255), | ||
+ | @user_name varchar(30), | ||
+ | @user_table_nm varchar(300) | ||
+ | |||
+ | open c2 | ||
+ | |||
+ | fetch c2 into @user_name, @table_name, @table_id, @colidarray | ||
+ | |||
+ | while @@sqlstatus = 0 | ||
+ | begin | ||
+ | select @colstring = "" | ||
+ | |||
+ | /* Decode the varbinary into usable column names */ | ||
+ | while @colidarray != null | ||
+ | begin | ||
+ | select @colid = left(@colidarray,2), | ||
+ | @colidarray = substring(@colidarray,3,255) | ||
+ | |||
+ | select @colnum = convert(smallint,@colid) | ||
+ | |||
+ | if @colstring != "" | ||
+ | select @colstring = @colstring | ||
+ | + "," | ||
+ | + name | ||
+ | from syscolumns | ||
+ | where id = @table_id | ||
+ | and colid = @colnum | ||
+ | else | ||
+ | select @colstring = name | ||
+ | from syscolumns | ||
+ | where id = @table_id | ||
+ | and colid = @colnum | ||
+ | end | ||
+ | |||
+ | set @user_table_nm = @user_name + "." + @table_name | ||
+ | |||
+ | print "update statistics %1! (%2!)", | ||
+ | @user_table_nm, | ||
+ | @colstring | ||
+ | |||
+ | fetch c2 into @user_name, @table_name, @table_id, @colidarray | ||
+ | end | ||
+ | |||
+ | close c2 | ||
+ | go | ||
+ | |||
+ | deallocate cursor c2 | ||
+ | go | ||
+ | |||
+ | Notes | ||
+ | * After the creation of statistics with "update statistics", the row in the sysstatistics table with formatid = 110, is automatically removed. | ||
+ | * Since "update statistics" records statistical info based on data in a table, it cannot create that for tables with no rows. This means that the entry in sysstatistics with formatid = 110 will not disappear. | ||
+ | * You can also take a look at the QPTune utility, located in $SYBASE/$SYBASE_ASE/qptune | ||
+ | |||
+ | ==ASE 15.0.2== | ||
Below is a method described to capture information from the optimizer once it finds that some statistical information is missing. It is based on the creation of a global login trigger where a trace option is enabled. The trace output from the optimizer is written into the errorlog where it can be captured by the DBA. | Below is a method described to capture information from the optimizer once it finds that some statistical information is missing. It is based on the creation of a global login trigger where a trace option is enabled. The trace output from the optimizer is written into the errorlog where it can be captured by the DBA. | ||
− | ==Create a stored procedure== | + | ===Create a stored procedure=== |
use sybsystemprocs | use sybsystemprocs | ||
Line 18: | Line 108: | ||
go | go | ||
− | ==Setup the permissions== | + | ===Setup the permissions=== |
Every login in the server should be able to execute the stored procedure. | Every login in the server should be able to execute the stored procedure. | ||
grant execute on sp_dba_globallogin to public | grant execute on sp_dba_globallogin to public | ||
Line 26: | Line 116: | ||
go | go | ||
− | ==Configure the stored procedure as a global login trigger== | + | ===Configure the stored procedure as a global login trigger=== |
sp_logintrigger "sp_dba_globallogin" | sp_logintrigger "sp_dba_globallogin" | ||
go | go | ||
Line 33: | Line 123: | ||
go | go | ||
− | ==Sample output in the errorlog== | + | ===Sample output in the errorlog=== |
NO STATS on column #spdbusages.vdevno | NO STATS on column #spdbusages.vdevno | ||
NO STATS on column #spdbusages.dbid | NO STATS on column #spdbusages.dbid | ||
Line 40: | Line 130: | ||
NO STATS on density set for master.dbo.spt_values={msgnum, type} | NO STATS on density set for master.dbo.spt_values={msgnum, type} | ||
− | ==Notes== | + | ===Notes=== |
* Statistics for temporary tables are also traced and written into the errorlog | * Statistics for temporary tables are also traced and written into the errorlog | ||
* Multiple sessions that are tracing at the same time cause garbled messages in the errorlog | * Multiple sessions that are tracing at the same time cause garbled messages in the errorlog | ||
[[Category:ASE]] | [[Category:ASE]] |
Revision as of 18:26, 16 July 2009
ASE 15 requires a lot more statistical information to make an optimal queryplan. In ASE 12 it was sufficient to run "update index statistics" on all tables but now also other columns in a query need up to date statistics.
There are two known methods available.
Contents
ASE 15.0.3 ESD 1 or later
Configure the server to capture missing statistics
sp_configure "capture missing statistics",1 go
This configuration option will store all missing statistical info into the sysstatistics system table, per database. On a regular basis you can query this table and generate statistics. Missing statistics can be found through formatid, it will have a value of 110. Each time a missing statistic has been detected it is recorded in the sysstatistics table and the column c0 contains a running total for each miss. Column c0 records this as a hexadecimal value, wrapping at 0xffff to x00000.
Sample query for sysstatistics
set flushmessage on set nocount on go declare c2 cursor for select distinct user_name(so.uid),so.name,so.id,st.colidarray from sysobjects so, sysstatistics st where so.type = "U" -- User tables and not (so.sysstat2 & 1024 = 1024 or -- Remote so.sysstat2 & 2048 = 2048) -- Proxy and st.id = so.id and st.formatid = 110 -- Missing order by 1,2 go exec sp_flushstats go declare @colid varbinary(2), @colidarray varbinary(100), @colnum tinyint, @colstring varchar(1024), @table_id int, @table_name varchar(255), @user_name varchar(30), @user_table_nm varchar(300) open c2 fetch c2 into @user_name, @table_name, @table_id, @colidarray while @@sqlstatus = 0 begin select @colstring = "" /* Decode the varbinary into usable column names */ while @colidarray != null begin select @colid = left(@colidarray,2), @colidarray = substring(@colidarray,3,255) select @colnum = convert(smallint,@colid) if @colstring != "" select @colstring = @colstring + "," + name from syscolumns where id = @table_id and colid = @colnum else select @colstring = name from syscolumns where id = @table_id and colid = @colnum end set @user_table_nm = @user_name + "." + @table_name print "update statistics %1! (%2!)", @user_table_nm, @colstring fetch c2 into @user_name, @table_name, @table_id, @colidarray end close c2 go deallocate cursor c2 go
Notes
- After the creation of statistics with "update statistics", the row in the sysstatistics table with formatid = 110, is automatically removed.
- Since "update statistics" records statistical info based on data in a table, it cannot create that for tables with no rows. This means that the entry in sysstatistics with formatid = 110 will not disappear.
- You can also take a look at the QPTune utility, located in $SYBASE/$SYBASE_ASE/qptune
ASE 15.0.2
Below is a method described to capture information from the optimizer once it finds that some statistical information is missing. It is based on the creation of a global login trigger where a trace option is enabled. The trace output from the optimizer is written into the errorlog where it can be captured by the DBA.
Create a stored procedure
use sybsystemprocs go create procedure sp_dba_globallogin as dbcc traceon(3605) set option show_missing_stats on return 0 go
Setup the permissions
Every login in the server should be able to execute the stored procedure.
grant execute on sp_dba_globallogin to public go
Allow all users to start optimizer tracing
grant set tracing to public go
Configure the stored procedure as a global login trigger
sp_logintrigger "sp_dba_globallogin" go
To disable the global login trigger run:
sp_logintrigger "drop" go
Sample output in the errorlog
NO STATS on column #spdbusages.vdevno NO STATS on column #spdbusages.dbid NO STATS on column #spdbusages.lstart NO STATS on density set for #spdbusages={vdevno, dbid} NO STATS on density set for master.dbo.spt_values={msgnum, type}
Notes
- Statistics for temporary tables are also traced and written into the errorlog
- Multiple sessions that are tracing at the same time cause garbled messages in the errorlog