<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://sqlblog.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results matching tags 'Internals' and 'metadata'</title><link>http://sqlblog.com/search/SearchResults.aspx?o=DateDescending&amp;tag=Internals,metadata&amp;orTags=0</link><description>Search results matching tags 'Internals' and 'metadata'</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP2 (Build: 61129.1)</generator><item><title>Geek City: Exploring the Transaction Log Structure</title><link>http://sqlblog.com/blogs/kalen_delaney/archive/2009/12/21/exploring-the-transaction-log-structure.aspx</link><pubDate>Tue, 22 Dec 2009 00:48:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:20158</guid><dc:creator>Kalen Delaney</dc:creator><description>&lt;P&gt;As I mentioned last October, my PASS preconference seminar was a &lt;A href="http://sqlblog.com/blogs/kalen_delaney/archive/2009/10/31/a-whole-day-of-transaction-log-info.aspx" target=_blank&gt;whole day about the transaction log&lt;/A&gt;. I told the attendees all kinds of things about the structure of the log, and told them about one of the best tools for exploring the structure: the command DBCC LOGINFO. This command is officially undocumented, but numerous bloggers have discussed it in some detail, including &lt;A href="http://www.mssqltips.com/tip.asp?tip=1225" target=_blank&gt;here&lt;/A&gt;. I'm not going to go into all the details here, but I'll be writing some related blog posts over the next month or so.&amp;nbsp; To understand DBCC LOGINFO you need to know about VLFs (Virtual Log Files) and one of the best places to read about VLFs is in &lt;A href="http://technet.microsoft.com/en-us/magazine/2009.02.logging.aspx" target=_blank&gt;Paul Randal's TechNet article&lt;/A&gt;. The DBCC LOGINFO command returns one row per VLF including the following columns:&lt;/P&gt;
&lt;P&gt;FileId &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;If you only have one physical log file, this value will be the same in every row. If you have multiple log files, you can use this value to explore the order that the SQL Server will fill up VLFs in multiple files. (More details in a future post.)&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;FileSize&amp;nbsp; &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;This value is in bytes. If you have your log file growth set to a percentage (which, unfortunately is the default), you should notice this value getting progressively larger as more VLFs are added to your log file.&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;StartOffset &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;This value is also in bytes, and is used as the sort column for the output. That is, the output from DBCC LOGINFO (if you only have single physical file) will be ordered by StartOffset. Notice that the first VLF always starts at offset 8192, which is the number of bytes in a page. The first page of the physical file is the file header, and does not store log records.&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;FSeqNo &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;The File Sequence Number indicates the order of usage of the VLFs. The row with the highest FSeqNo value is the VLF where current log records are being written. Notice that the FSeqNo values are not always consistent with the StartOffset, as VLFs are reusable after the log has been truncate. I'll discuss this value more in a future post, or you can get some info from Paul's article on how and when a VLF is reused. A value of 0 for the FSeqNo means that this VLF has never been used at all yet.&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Status &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Status has two possible values: 0 and 2. I'll be discussing these values in a lot more detail later. For now, the simple definition is that a value of 2 means the VLF is not reusable and a value of 0 means it is.&lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;BR&gt;Parity &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;Parity has two possible values: 64 and 128. Every time a VLF is reused, the parity value is switched. Paul Randal discusses the parity value in more detail in &lt;/EM&gt;&lt;A href="http://www.sqlskills.com/BLOGS/PAUL/post/Search-Engine-QA-24-Why-cant-the-transaction-log-use-instant-initialization.aspx" target=_blank&gt;&lt;EM&gt;this article.&lt;/EM&gt;&lt;/A&gt;&lt;EM&gt; &lt;BR&gt;&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;CreateLSN &lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;EM&gt;This value indicates when the VLF was created. If the CreateLSN is 0, it means the VLF was original equipment, created when the database was created. You can use this value to see how many VLFs were added each time the log grew. VLFs with the same CreateLSN value were created at the same time. &lt;/EM&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The whole point of describing all these columns was just to provide a lead-in to my little holiday gift to you. Here is a table that can be created in the master database, and then populated with the output of DBCC LOGINFO. The name of the table starts with sp_, which means you can use it from any database.&amp;nbsp; Once you have captured all the rows from DBCC LOGINFO, you can query them using any TSQL queries.&lt;/P&gt;
&lt;P&gt;Here the table creation script:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=1 face="Courier New"&gt;USE master &lt;BR&gt;GO &lt;BR&gt;IF EXISTS&amp;nbsp; (SELECT 1 FROM sys.tables &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE name = 'sp_LOGINFO') &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DROP TABLE sp_loginfo; &lt;BR&gt;GO &lt;BR&gt;CREATE TABLE sp_LOGINFO &lt;BR&gt;(FileId tinyint, &lt;BR&gt;FileSize bigint, &lt;BR&gt;StartOffset bigint, &lt;BR&gt;FSeqNo int, &lt;BR&gt;Status tinyint, &lt;BR&gt;Parity tinyint, &lt;BR&gt;CreateLSN numeric(25,0) ); &lt;BR&gt;GO&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;And here is how to populate it. I will use the &lt;EM&gt;AdventureWorks&lt;/EM&gt; database for the example:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=1 face="Courier New"&gt;USE AdventureWorks; &lt;BR&gt;GO &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=1 face="Courier New"&gt;TRUNCATE TABLE sp_LOGINFO; &lt;BR&gt;INSERT INTO sp_LOGINFO &lt;BR&gt;&amp;nbsp;&amp;nbsp; EXEC ('DBCC LOGINFO');&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You can select the VLFs from most recently used to the least:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT size=1 face="courier new"&gt;SELECT * FROM sp_LOGINFO &lt;BR&gt;ORDER BY FSeqNo DESC;&lt;/FONT&gt; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You can count how many VLFs have each status value:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=1 face="Courier New"&gt;SELECT status, COUNT(*) FROM sp_LOGINFO &lt;BR&gt;GROUP BY status;&lt;/FONT&gt; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;If you don't have a lot of VLFs, you can try to generate more by running SELECT INTO repeatedly. Make sure you are in FULL recovery to get the most log growth:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT size=1 face="Courier New"&gt;SELECT * INTO dbo.Orders FROM AdventureWorks.Sales.SalesOrderDetail; &lt;BR&gt;DROP TABLE dbo.Orders; &lt;BR&gt;GO 5&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT size=1 face="Courier New"&gt;TRUNCATE TABLE sp_LOGINFO; &lt;BR&gt;INSERT INTO sp_LOGINFO &lt;BR&gt;&amp;nbsp;&amp;nbsp; EXEC ('DBCC LOGINFO');&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT size=1 face="Courier New"&gt;SELECT status, COUNT(*) FROM sp_LOGINFO &lt;BR&gt;GROUP BY status WITH ROLLUP;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You may be able to figure out other queries that provide useful or interesting information for you. I'll refer back to this table in my future discussions on DBCC LOGINFO and VLFs.&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff size=4&gt;~Kalen&lt;/FONT&gt;&lt;/P&gt;</description></item><item><title>Geek City: Fragmentation on the System Tables</title><link>http://sqlblog.com/blogs/kalen_delaney/archive/2008/01/17/fragmentation-on-the-system-tables.aspx</link><pubDate>Fri, 18 Jan 2008 01:05:00 GMT</pubDate><guid isPermaLink="false">21093a07-8b3d-42db-8cbf-3350fcbf5496:4576</guid><dc:creator>Kalen Delaney</dc:creator><description>&lt;P&gt;It's my first post of the new year. I hope it's starting out well for all of you! New year, but sometimes the same old questions. I got another email asking about defragging the system tables. It seems to be in the Hit Parade of FAQs. &lt;/P&gt;
&lt;P&gt;First of all, WHY do you think you would need to defrag a system table? Fragmentation is only a problem when you are performing an in-order scan on a table of more than 100 pages or so, and how often do you do that to a system table that is that big? Rarely, I would assume, but let me know if you have seen an actual need for defragging a system table.&lt;/P&gt;
&lt;P&gt;In SQL Server 2000, you can actually use a system table as a parameter to DBCC SHOWCONTIG to see the fragmentation values. One of my readers reported that he tried running a DBCC INDEXDEFRAG on SQL 2000 system tables and while sometimes it worked, sometimes it corrupted the table! It doesn't sound worth it to me. &lt;/P&gt;
&lt;P&gt;And now, with SQL Server 2005 there is no way to see the fragmentation on the system tables. What about using the new Dynamic Management Object sys.dm_db_index_physical_stats? It requires an object_id as a parameter, and if you select from the metadata view sys.all_objects you can see the object_id for the real system tables, even if you're not using the DAC. Try this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#004080&gt;select * from sys.all_objects&lt;BR&gt;where type = 'S'&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You should see all the system tables in your current database, and their object IDs. So you could try passing the id to the management view. Here I'll try it for &lt;EM&gt;syshobts&lt;/EM&gt;, which has an ID of 15:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#000080&gt;&lt;FONT face="Courier New"&gt;select * from &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;sys.dm_db_index_physical_stats(1, 15, null, null, 'detailed')&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;No results are returned. If I replace the 15 with null, to indicate I want all objects, I do not see any objects with IDs less than 100, which means there are no system objects reported.&lt;/P&gt;
&lt;P&gt;I did notice one interesting behavior while playing around with this concept. If I use the old DBCC SHOWCONTIG and try to get a report for a system table, this command gives me an error:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="courier new" color=#004080&gt;dbcc showcontig ('syshobts')&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new" color=#ff0000&gt;Msg 2501, Level 16, State 45, Line 1&lt;BR&gt;Cannot find a table or object with the name "syshobts". Check the system catalog.&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;However, if I qualify the table name with the schema name, something different happens.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="courier new" color=#004080&gt;dbcc showcontig ('sys.syshobts')&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This time, I don't get an error. I don't get a fragmentation report, but I don't get an error. I just get the message that DBCC execution completed. So it's obvious that there is a difference here. If I then intentionally misspell the object name&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="courier new" color=#004080&gt;dbcc showcontig ('sys.syshobbits')&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;now I get the error that SQL Server cannot find the object. So it seems that in SQL Server 2005, DBCC SHOWCONTIG is deliberately filtering out the real system tables, and it was by design to not return fragmentation information. So even if you could run defrag on your system tables, you could never know what impact you had!&lt;/P&gt;
&lt;P&gt;I think there's better ways to spend our time.&lt;/P&gt;
&lt;P&gt;Have fun!&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff00ff&gt;~Kalen&lt;/FONT&gt;&lt;/P&gt;</description></item></channel></rss>