Showing posts with label tuning. Show all posts
Showing posts with label tuning. Show all posts

Wednesday, February 22, 2012

[tuning] Statistics - when were they created... OR RECENTLY UPDATED?

(update 2013/08/07 - since it shows recent times...)

Courtesy of Nayan Raval & #SQLHelp, which led me to another article (http://blogs.solidq.com/fabianosqlserver/post.aspx?id=52&title=undocumented+option(querytraceon+%3Ctracenumber%3E)+and+trace+flags+2388%2C+2389%2C+2390) which documents 2 more undocumented trace flags.

How do you find out when statistics were created?  If it's on an indexed field, when the index was created (crdate in sys.indexes).  But statistics on non-indexed fields?  Using Trace Flag 2388 changes the information that SHOW_STATISTICS returns.


DBCC TRACEON (2388)
DBCC SHOW_STATISTICS ('yourtablename','_WA_Sys_x')
DBCC TRACEOFF (2388)

Look for the row with the oldest Updated. The oldest update, depending on how often it's been updated, MAY show you when it was created.

And there's another use for this trace flag... when, aside from the most-recent date, was a statistic updated?   STATS_DATE will show you the LAST time it was updated, but I recently had a problem where I knew the problem existed and quickly updated stats, then realized I wanted to know when BEFORE then it had been updated.  One search to my blog later, code found, and there we go.

Thursday, September 1, 2011

[Index] Size, usage, and location of your indexes

Updated my old code, since we were trying to figure out what indexes needed to get moved to the secondary (index) filegroup. You can even filter based off the usage (commented out below)
Standard disclaimer applies. Select the contents of the post, then copy/paste.

Note that there can be dupes - this is by design.  If a table spans multiple files, you'll see multiple rows returned with everything identical except for the filename.

SELECT
        o.name AS Table_Name ,
        i.NAME AS Index_Name ,
--        i.type_desc,
  CASE i.type
   WHEN 0 THEN 'Heap'
   WHEN 1 THEN 'C'
   WHEN 2 THEN 'NC'
   ELSE '?' END AS [Type],
   p.partition_number,
   p.rows AS [#Records] ,
        a.total_pages * 8 / 1024 AS [Reserved(mb)] ,
        a.used_pages * 8 / 1024 AS [Used(mb)] ,
        s.user_seeks ,
        s.user_scans ,
        s.user_lookups,
        fg.name, 
        f.name,
        f.physical_name
FROM    sys.indexes AS i
        INNER JOIN sys.partitions AS p 
   ON i.object_id = p.object_id
            AND i.index_id = p.index_id
        INNER JOIN SYS.OBJECTS O 
   ON I.OBJECT_ID = O.OBJECT_ID
        INNER JOIN sys.allocation_units AS a 
   ON ( a.type = 2
    AND p.partition_id = a.container_id
               )
   OR 
    ( ( a.type = 1 OR a.type = 3)
    AND p.hobt_id = a.container_id)
        INNER JOIN SYS.DM_DB_INDEX_USAGE_STATS S 
   ON S.OBJECT_ID = I.OBJECT_ID
   AND I.INDEX_ID = S.INDEX_ID
   AND DATABASE_ID = DB_ID(DB_NAME())
   AND o.type_desc NOT IN ( 'SYSTEM_TABLE', 'INTERNAL_TABLE' ) -- No system tables!
  LEFT OUTER JOIN sys.database_files f 
   ON f.data_space_id = a.data_space_id
  LEFT OUTER JOIN sys.filegroups fg 
   ON fg.data_space_id = a.data_space_id
WHERE   OBJECTPROPERTY(O.OBJECT_ID, 'IsUserTable') = 1
        AND i.TYPE_DESC <> 'HEAP'
        AND i.type <> 1 -- clustered index
--AND (ISNULL(s.user_seeks, 0) + ISNULL(s.user_scans, 0) + ISNULL(s.user_lookups, 0)) < 100 
ORDER BY o.NAME ,
        i.name

Monday, August 15, 2011

[Tuning] Disk usage over time, checking deltas

Not sure where this came from, if I wrote it or someone else did. Practically, it looks before and after to tell you which files are getting used. The commented out bit was because I was investigating WRITELOG delays.



--as always, drag-copy to get the full text.
DECLARE @compare TABLE (NAME sysname, type_desc varchar(10), physical_name VARCHAR(200), sample_ms BIGINT,
num_of_bytes_written BIGINT, num_of_bytes_read BIGINT, size_in_gb INT)
DECLARE @compare2 TABLE (NAME sysname, type_desc varchar(10), physical_name VARCHAR(200), sample_ms BIGINT,
num_of_bytes_written BIGINT, num_of_bytes_read BIGINT, size_in_gb INT)

INSERT INTO @compare
SELECT
master_files.NAME,
master_files.type_desc,
master_files.physical_name,
vfs.sample_ms,
vfs.num_of_bytes_written,
num_of_bytes_read,
size_on_disk_bytes/1024/1024/1024 AS Size_in_GB
FROM sys.dm_io_virtual_file_stats(null, null) vfs
INNER JOIN MASTER.sys.master_files
ON vfs.[file_id] = master_files.[file_id]
AND vfs.database_id = master_files.database_id
--WHERE type_desc = 'log'
ORDER BY (num_of_bytes_read + num_of_bytes_written) DESC

WAITFOR DELAY '00:00:15'

INSERT INTO @compare2
SELECT
master_files.NAME,
master_files.type_desc,
master_files.physical_name,
vfs.sample_ms,
vfs.num_of_bytes_written,
num_of_bytes_read,
size_on_disk_bytes/1024/1024/1024 AS Size_in_GB
FROM sys.dm_io_virtual_file_stats(null, null) vfs
INNER JOIN MASTER.sys.master_files
ON vfs.[file_id] = master_files.[file_id]
AND vfs.database_id = master_files.database_id
-- WHERE type_desc = 'log'
ORDER BY (num_of_bytes_read + num_of_bytes_written) DESC


SELECT old.NAME, old.physical_name, new.sample_ms - old.sample_ms AS time_elapsed,
new.num_of_bytes_written - old.num_of_bytes_written AS delta_num_bytes_written,
new.num_of_bytes_read - old.num_of_bytes_read AS delta_num_bytes_read, old.size_in_gb
FROM @compare old INNER JOIN @compare2 new ON old.physical_name = new.physical_name
ORDER BY (new.num_of_bytes_written - old.num_of_bytes_written) DESC


Tuesday, May 25, 2010

[Tuning] Getting only the DATE from a datetime

Many ways to handle dates, and most time I don't think about it - then came across a gigantic thread over two years that discussed it.


Comparing dates. Traditionally, for simplicity, to mark particular dates, I've used convert(char(8),a_date_field,12), but it’s non-SARGable, and not terribly efficient.


Looking online I found a couple alternatives, though they’re mostly useful when having to deal with large tables.

http://blog.sqlauthority.com/2008/10/18/sql-server-retrieve-select-only-date-part-from-datetime-best-practice-part-2/

For SQL Server 2008 it's pretty simple:

SELECT cast(GETDATE() as date)
or
SELECT CONVERT(date,GETDATE())


(date is a new datatype that only stores the date, and is 3 bytes in size)

For SQL Server 2005, there seem to be two options. Naturally, neither is SARGable from what I’ve seen.


SELECT CONVERT (datetime, FLOOR(CONVERT (float, a_field_name)))
and
SELECT DATEADD ( DAY, DATEDIFF(DAY, 0, a_field_name), 0)


The first one performs math on the internally-stored FLOAT value of the datetime - right now, for instance, is 40315.37003125, where the whole number is the day and the fraction is the time. (Note that you can’t cheat and use INT; it can round up during the conversion).

The second one does date manipulation - there's a whole article online about using datediff and dateadd and the like to get the first day of the month, the first day of last month, etc, etc.

From what I’ve seen online, the FLOOR option can be slightly faster than the DATEADD, but either is considerably faster than CONVERT(char(8)).

Wednesday, October 28, 2009

[Tuning] Getting file disk usage

Short and simple. Uses the DMV to tell you how much IO each file is using. What you think may be the case is not necessarily the case. And remember that backups count. I'd recommend doing 2+ samples during the day, and comparing. That'll help remove the backups from the end totals. Sample_MS is the number of milliseconds the computer has been up.

SELECT 
  master_files.NAME, 
  master_files.type_desc,
  master_files.physical_name, 
  vfs.sample_ms,
  vfs.num_of_bytes_written, 
  num_of_bytes_read, 
  size_on_disk_bytes/1024/1024/1024 AS Size_in_GB
FROM sys.dm_io_virtual_file_stats(null, null) vfs
INNER JOIN MASTER.sys.master_files 
 ON vfs.[file_id] = master_files.[file_id] 
 AND vfs.database_id = master_files.database_id
ORDER BY (num_of_bytes_read + num_of_bytes_written) desc