<?xml version="1.0" encoding="utf-8"?><!-- generator="b2evolution/6.11.7-stable" -->
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>SQL Server &#38; BI Blog by Andreas Wolter - Category: "Miscellaneous"</title>
		<link>https://www.insidesql.org/blogs/andreaswolter/</link>
		<atom:link rel="self" type="application/rss+xml" href="https://www.insidesql.org/blogs/andreaswolter/?tempskin=_rss2" />
		<description>InsideSQL.org Blogs - Blogs über SQL Server</description>
		<language>en-EU</language>
		<docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<admin:generatorAgent rdf:resource="http://b2evolution.net/?v=6.11.7-stable"/>
		<ttl>60</ttl>
				<item>
			<title>Dieser Blog ist umgezogen // This Blog has moved: http://andreas-wolter.com/blog/</title>
			<link>https://www.insidesql.org/blogs/andreaswolter/2017/09/blog-umgezogen-this-blog-moved-andreas-wolter-com</link>
			<pubDate>Wed, 20 Sep 2017 10:41:00 +0000</pubDate>			<dc:creator>Andreas Wolter</dc:creator>
			<category domain="alt">Seminare</category>
<category domain="alt">SQLPASS</category>
<category domain="alt">Tracing &amp; Monitoring</category>
<category domain="alt">Analysis Services</category>
<category domain="alt">Extended Events</category>
<category domain="alt">Conferences</category>
<category domain="alt">Oracle</category>
<category domain="alt">Security</category>
<category domain="alt">Locking &amp; Blocking</category>
<category domain="alt">SQL Trace &amp; Profiler</category>
<category domain="alt">SQL Server 2014</category>
<category domain="alt">Indexing</category>
<category domain="alt">Columnstore Index</category>
<category domain="alt">APS/Parallel Data Warehouse</category>
<category domain="alt">Reporting Services</category>
<category domain="alt">Integration Services</category>
<category domain="main">Miscellaneous</category>
<category domain="alt">Geospatial</category>
<category domain="alt">Certification, MCM &amp; MCSM, MVP</category>
<category domain="alt">In-Memory OLTP / XTP, HTAP</category>
<category domain="alt">Surveys / Umfragen</category>
<category domain="alt">Scripts</category>
<category domain="alt">HADR, AlwaysOn</category>
<category domain="alt">MDW</category>
<category domain="alt">Storage Engine</category>
<category domain="alt">Trivia</category>
<category domain="alt">Azure</category>
<category domain="alt">Performance</category>
<category domain="alt">SQL Server 2016</category>
<category domain="alt">Patching</category>			<guid isPermaLink="false">3918@https://www.insidesql.org/blogs/</guid>
						<description>&lt;p&gt;&lt;a href=&quot;http://andreas-wolter.com/blog/&quot;&gt;http://andreas-wolter.com/blog/&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;302&quot;&gt;
&lt;p&gt;Liebe Leser&lt;br /&gt; dieser Blog ist hiermit nur noch „Archiv“ und wird nicht mehr weiter gepflegt.&lt;br /&gt; Seit August 2017 finden sich neue Artikel ausschließlich unter der &lt;strong&gt;neuen URL:&lt;br /&gt; &lt;a href=&quot;http://andreas-wolter.com/blog/&quot;&gt;http://andreas-wolter.com/blog/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width=&quot;302&quot;&gt;
&lt;p&gt;Dear Readers&lt;br /&gt; this blog is now merely an „archive“ and no longer being updated.&lt;br /&gt; Since August 2017 new articles are exclusively available under the &lt;strong&gt;new URL:&lt;br /&gt; &lt;a href=&quot;http://andreas-wolter.com/en/blog/&quot;&gt;http://andreas-wolter.com/en/blog/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;302&quot;&gt;
&lt;p&gt;Die aufwändige Mehrsprachigkeit (Deutsch und Englisch professionell manuell übersetzt) wird beibehalten – aber Layout-technisch anders gelöst. Damit dürfte ich immer noch den einzigen mehrsprachigen IT-Blog weltweit betreiben.&lt;br /&gt; Ich hoffe, das neue Design gefällt Ihnen.&lt;/p&gt;
&lt;/td&gt;
&lt;td width=&quot;302&quot;&gt;
&lt;p&gt;The complex multilingualism (German and English professionally manually translated) is being continued – but solved differently in terms of layout. With that I most likely still operate the only multilingual IT-Blog worldwide.&lt;br /&gt; I hope you like the new design.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;div class=&quot;image_block&quot;&gt;&lt;a href=&quot;http://andreas-wolter.com/blog/&quot;&gt;&lt;img class=&quot;loadimg&quot; src=&quot;http://www.insidesql.org/blogs/media/blogs/andreaswolter/quick-uploads/p3918/170918_website_blog.jpg?mtime=1505903940&quot; alt=&quot;&quot; width=&quot;800&quot; height=&quot;552&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;302&quot;&gt;
&lt;p&gt;Mein aktueller Artikel, der erstmalig ausschließlich auf der neuen Website zu finden ist, lautet: &lt;strong&gt;&lt;a href=&quot;http://andreas-wolter.com/optimierung-von-workflows-mit-inmemory-objekten/&quot;&gt;Optimieren von Workflows mit In-Memory und nativ kompilierten Objekten - oder wie es nicht funktioniert&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td width=&quot;302&quot;&gt;
&lt;p&gt;My currently last article, which is exclusively available at the new website for the first time, is &lt;strong&gt;&lt;a href=&quot;http://andreas-wolter.com/en/optimizing-workflows/&quot;&gt;Optimizing workflows with In-Memory and Natively Compiled Objects - or how it does not work&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Cu at my new Blog&lt;/p&gt;
&lt;p&gt;Andreas&lt;/p&gt;</description>
			<content:encoded><![CDATA[<p><a href="http://andreas-wolter.com/blog/">http://andreas-wolter.com/blog/</a></p>
<table>
<tbody>
<tr>
<td width="302">
<p>Liebe Leser<br /> dieser Blog ist hiermit nur noch „Archiv“ und wird nicht mehr weiter gepflegt.<br /> Seit August 2017 finden sich neue Artikel ausschließlich unter der <strong>neuen URL:<br /> <a href="http://andreas-wolter.com/blog/">http://andreas-wolter.com/blog/</a></strong></p>
</td>
<td width="302">
<p>Dear Readers<br /> this blog is now merely an „archive“ and no longer being updated.<br /> Since August 2017 new articles are exclusively available under the <strong>new URL:<br /> <a href="http://andreas-wolter.com/en/blog/">http://andreas-wolter.com/en/blog/</a></strong></p>
</td>
</tr>
<tr>
<td width="302">
<p>Die aufwändige Mehrsprachigkeit (Deutsch und Englisch professionell manuell übersetzt) wird beibehalten – aber Layout-technisch anders gelöst. Damit dürfte ich immer noch den einzigen mehrsprachigen IT-Blog weltweit betreiben.<br /> Ich hoffe, das neue Design gefällt Ihnen.</p>
</td>
<td width="302">
<p>The complex multilingualism (German and English professionally manually translated) is being continued – but solved differently in terms of layout. With that I most likely still operate the only multilingual IT-Blog worldwide.<br /> I hope you like the new design.</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<div class="image_block"><a href="http://andreas-wolter.com/blog/"><img class="loadimg" src="http://www.insidesql.org/blogs/media/blogs/andreaswolter/quick-uploads/p3918/170918_website_blog.jpg?mtime=1505903940" alt="" width="800" height="552" /></a></div>
<p> </p>
<table>
<tbody>
<tr>
<td width="302">
<p>Mein aktueller Artikel, der erstmalig ausschließlich auf der neuen Website zu finden ist, lautet: <strong><a href="http://andreas-wolter.com/optimierung-von-workflows-mit-inmemory-objekten/">Optimieren von Workflows mit In-Memory und nativ kompilierten Objekten - oder wie es nicht funktioniert</a></strong></p>
</td>
<td width="302">
<p>My currently last article, which is exclusively available at the new website for the first time, is <strong><a href="http://andreas-wolter.com/en/optimizing-workflows/">Optimizing workflows with In-Memory and Natively Compiled Objects - or how it does not work</a></strong></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p>Cu at my new Blog</p>
<p>Andreas</p>]]></content:encoded>
								<comments>https://www.insidesql.org/blogs/andreaswolter/2017/09/blog-umgezogen-this-blog-moved-andreas-wolter-com#comments</comments>
			<wfw:commentRss>https://www.insidesql.org/blogs/andreaswolter/?tempskin=_rss2&#38;disp=comments&#38;p=3918</wfw:commentRss>
		</item>
				<item>
			<title>Maximum number of rows per data page and minimal record size (SQL Server storage internals)</title>
			<link>https://www.insidesql.org/blogs/andreaswolter/2014/10/maximale-anzahl-zeilen-je-datenseite-max-row-data-page-in-sql-server</link>
			<pubDate>Wed, 29 Oct 2014 09:30:00 +0000</pubDate>			<dc:creator>Andreas Wolter</dc:creator>
			<category domain="alt">Miscellaneous</category>
<category domain="main">Storage Engine</category>
<category domain="alt">Trivia</category>			<guid isPermaLink="false">3740@https://www.insidesql.org/blogs/</guid>
						<description>&lt;p&gt;Maximale Anzahl Zeilen je Datenseite und minimale Datensatzgröße&lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;(DE)&lt;br /&gt; In einer meiner letzten Master-Classes tauchte die nicht ganz ernste aber dennoch interessante Fragestellung auf:&lt;/p&gt;
&lt;p&gt;Wie viele Zeilen passen eigentlich maximal auf eine Datenseite? – wenn die Datensätze/Records so klein wie möglich sind.&lt;/p&gt;
&lt;p&gt;Zunächst, &lt;strong&gt;Part 1&lt;/strong&gt;, was ist der kleinstmögliche Datensatz in SQL Server?&lt;/p&gt;
&lt;p&gt;Um das zu beurteilen, ist es gut, die Datentypen sowie die Struktur eines Datensatzes genau zu kennen.&lt;br /&gt; Man könnte versucht sein, anzunehmen, dass eine Spalte vom Datentyp &lt;em&gt;bit&lt;/em&gt; der kleinstmögliche Datensatz ist. Der erfahrene SQL‘er wird wissen, dass ein &lt;em&gt;bit&lt;/em&gt; allein auch immer mindestens 1 &lt;em&gt;byte&lt;/em&gt; in einem Record benötigt – erst bei mehreren Spalten dieses Datentyps, kommt ein Platzersparnis ins Spiel (&lt;a href=&quot;http://msdn.microsoft.com/de-de/library/ms177603.aspx&quot; target=&quot;_blank&quot;&gt;bit (Transact-SQL)&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Der nächste Kandidat sind Datentypen, die laut der &lt;a href=&quot;http://msdn.microsoft.com/de-de/library/ms187752.aspx&quot; target=&quot;_blank&quot;&gt;Liste in Books Online&lt;/a&gt; nur &lt;strong&gt;1 byte&lt;/strong&gt; Speicherplatz benötigen. Das wären folgende:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;(EN)&lt;br /&gt; In one of my last Master classes, a not quite so serious but nevertheless interesting question was brought up:&lt;/p&gt;
&lt;p&gt;How many rows maximally do actually fit on a data page? – if the data sets/records are as small as possible.&lt;/p&gt;
&lt;p&gt;First of all, &lt;strong&gt;part 1&lt;/strong&gt;, what is the smallest possible data set in SQL Server?&lt;/p&gt;
&lt;p&gt;In order to assess this, it is commendable to know exactly the data types as well as the structure of a data set. &lt;/p&gt;
&lt;p&gt;One could be tempted to assume that a column of the data type &lt;em&gt;bit&lt;/em&gt; is the smallest possible data set. The experienced SQL people will know that a &lt;em&gt;bit&lt;/em&gt; alone always also requires at least 1 &lt;em&gt;byte&lt;/em&gt; in one record – only with several columns of this data type, the place-saving aspect comes into play (&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms177603.aspx&quot; target=&quot;_blank&quot;&gt;bit (Transact-SQL)&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The next candidate are data types which according to the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms187752.aspx&quot; target=&quot;_blank&quot;&gt;list in Books Online&lt;/a&gt; use only &lt;strong&gt;1 byte&lt;/strong&gt; of storage. These would be the following:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bit&lt;/li&gt;
&lt;li&gt;char(1)&lt;/li&gt;
&lt;li&gt;binary(1)&lt;/li&gt;
&lt;li&gt;tinyint&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Tatsächlich benötigen &lt;span style=&quot;text-decoration: underline;&quot;&gt;in diesem besonderen Fall&lt;/span&gt;, &lt;strong&gt;einer einzigen Spalte je Datensatz&lt;/strong&gt;, auch Records mit Nettowert von 2 Bytes, &lt;strong&gt;9 Bytes&lt;/strong&gt; auf der Datenseite:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;As a matter of fact, &lt;span style=&quot;text-decoration: underline;&quot;&gt;in this particular case&lt;/span&gt; of &lt;strong&gt;a single column per record&lt;/strong&gt;, also records with a net value of 2 bytes use &lt;strong&gt;9 bytes&lt;/strong&gt; on the data page:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;char(2)&lt;/li&gt;
&lt;li&gt;nchar(1)&lt;/li&gt;
&lt;li&gt;binary(2)&lt;/li&gt;
&lt;li&gt;smallint&lt;/li&gt;
&lt;/ul&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Wie kommt das?&lt;br /&gt; Das liegt an der Struktur der Datensätze. Diese ist hinlänglich in diversen Blogs dokumentiert (z.B. hier &lt;a href=&quot;http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-record/&quot; target=&quot;_blank&quot;&gt;Inside the Storage Engine: Anatomy of a record&lt;/a&gt; und hier: &lt;a href=&quot;https://www.simple-talk.com/sql/database-administration/sql-server-storage-internals-101/&quot; target=&quot;_blank&quot;&gt;SQL Server Storage Internals 101&lt;/a&gt; ), jedoch eher für allgemeine Zwecke und dieser Sonderfall (eine 1-byte-Spalte) ist dabei weniger im Fokus.&lt;/p&gt;
&lt;p&gt;Theoretisch würden für einen Datensatz 8 Bytes ausreichen:&lt;/p&gt;
&lt;p&gt;4 Bytes: Datensatzkopf (Typ + Zeiger auf Null-Bitmap)&lt;br /&gt;1 Byte: Daten&lt;br /&gt;2 Bytes: Anzahl der Spalten im Record&lt;br /&gt;1 Byte: NULL Bitmap&lt;/p&gt;
&lt;p&gt;Dazu kommt noch der 2 Bytes große Zeiger im Page-Offset, was dann 10 Bytes ergeben würde.&lt;br /&gt;Dennoch belegt ein solcher Datensatz 9 Bytes auf der Seite/Page + Offset.&lt;/p&gt;
&lt;p&gt;Woran das liegt, sehen wir uns an.&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;How come?&lt;br /&gt;This has to do with the structure of the data sets, which is sufficiently documented in various blogs (e.g. here: &lt;a href=&quot;http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-record/&quot; target=&quot;_blank&quot;&gt;Inside the Storage Engine: Anatomy of a record&lt;/a&gt; and here: &lt;a href=&quot;https://www.simple-talk.com/sql/database-administration/sql-server-storage-internals-101/&quot; target=&quot;_blank&quot;&gt;SQL Server Storage Internals 101&lt;/a&gt; ), but rather for general purposes, and this special case (a 1-byte-column) is less focused on here.&lt;/p&gt;
&lt;p&gt;Theoretically, 8 bytes would be sufficient for a data set:&lt;/p&gt;
&lt;p&gt;4 bytes: data set head (type + pointer to NULL-bitmap)&lt;br /&gt;1 byte: data&lt;br /&gt;2 bytes: number of columns in record&lt;br /&gt;1 byte: NULL bitmap&lt;/p&gt;
&lt;p&gt;Add to that the 2-bytes-pointer in the page offset, which would then result in 10 bytes.&lt;br /&gt;Despite this, such a data set uses 9 bytes on the page/page + offset.&lt;/p&gt;
&lt;p&gt;We will now look at the reason for this.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Im Folgenden definiere ich 2 Tabellen mit jeweils einer bzw. 2 Spalten von Datentyp &lt;em&gt;tinyint&lt;/em&gt;, der ja bekanntlich einen Byte benötigt:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;In the following, I am defining 2 tables with one and 2 columns each of the data type &lt;em&gt;tinyint&lt;/em&gt;, which is known to use 1 byte:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;CREATE TABLE T1col&lt;/pre&gt;
&lt;pre&gt;(col1 tinyint null)&lt;/pre&gt;
&lt;pre&gt;GO&lt;/pre&gt;
&lt;pre&gt;CREATE TABLE T2col&lt;/pre&gt;
&lt;pre&gt;(col1 tinyint null, col2 tinyint null)&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Danach füge ich zuerst Datenätze mit dem Wert „255“ bzw „255, 255“ ein, und danach einige mit Wert „NULL“.&lt;/p&gt;
&lt;p&gt;Mit DBCC Page kann man sich den Header der Datenseiten beider Tabellen ansehen, und findet eine kleine Überraschung (Ergebnis reduziert):&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Next, I am inserting, first, data set of the value “255” or “255, 255” and then a few of the value “NULL.”&lt;/p&gt;
&lt;p&gt;With the DBCC page, one can look at the header of the data pages of both tables, and one will find a small surprise (reduced result). &lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_DBCCPage_1vs2cols.png&quot; alt=&quot;DBCCPage_1vs2cols&quot; width=&quot;767&quot; height=&quot;801&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Obwohl die Größe der Daten fixer Länge (&lt;em&gt;pminlen&lt;/em&gt;) mit 5 bzw. 6 unterschiedlich angegeben wird, ist der freie Speicherplatz auf der Seite (&lt;em&gt;m_freeCnt&lt;/em&gt;) identisch! (&lt;em&gt;rot&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;Der Datensatz belegt in beiden Fällen jedoch 9 Bytes im Page-body (&lt;em&gt;blau&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;So sieht die Tabelle, bestehend aus &lt;span style=&quot;text-decoration: underline;&quot;&gt;einer Spalte&lt;/span&gt;, mit einigen Datensätzen gefüllt, auf der Festplatte aus:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Even though the size of the fixed-length data (&lt;em&gt;pminlen&lt;/em&gt;) is specified differently, with 5 and 6 respectively, the free storage on the page (&lt;em&gt;m_freeCnt&lt;/em&gt;) is identical! (&lt;em&gt;red&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;The record, however, uses in both cases 9 bytes in the page body. (&lt;em&gt;blue&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;This is what the table, consisting of &lt;span style=&quot;text-decoration: underline;&quot;&gt;one column&lt;/span&gt;, filled up with a few records, looks like on the hard drive:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;  &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Page_Record_1col9byte_hex.png&quot; alt=&quot;Page_Record_1col9byte_hex&quot; width=&quot;989&quot; height=&quot;157&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Man sieht, dass 9 Bytes belegt sind, jedoch nur, da nach der NULL Bitmap noch ein Byte jedem Datensatz anhängig ist (&lt;em&gt;gelb&lt;/em&gt; markiert).&lt;/p&gt;
&lt;p&gt;Hier die Tabelle mit &lt;span style=&quot;text-decoration: underline;&quot;&gt;2 Spalten&lt;/span&gt;:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;One can see that 9 bytes are used, but only because after the NULL bitmap, one extra byte is attached to each data set (marked in &lt;em&gt;yellow&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Below, see the table with 2 columns:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Page_Record_2cols9byte_hex.png&quot; alt=&quot;1410_Page_Record_2cols9byte_hex.png&quot; width=&quot;985&quot; height=&quot;153&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Auch hier also 9 Bytes, mit dem Unterschied, wie das letzte Byte verwendet wird.&lt;/p&gt;
&lt;p&gt;Noch etwas deutlicher wird es im Binärformat. Das ist die Tabelle mit 2 Spalten – auch diese benötigt 9 Bytes, und man sieht unten, wie die NULL Bitmap zu ihrem Namen kommt:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Here, too, it is 9 bytes, with the difference being how the last byte is used.&lt;/p&gt;
&lt;p&gt;It becomes a bit clearer in the binary format.&lt;br /&gt;This is the table with 2 columns –this one uses 9 bytes as well, and you can see below how the NULL bitmap gets its name:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Page_Record_2cols9byte_binary.png&quot; alt=&quot;Page_Record_2cols9byte_binary&quot; width=&quot;749&quot; height=&quot;231&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Dieser eine Byte, der für mich keinen klaren Nutzen hat, führt also zu dem Ergebnis, das beide Tabellen letztlich 9 Bytes je Record auf der Festplatte benötigen.&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;This one byte, which to me does not have any clear purpose, is what leads to the result that both tables ultimately use 9 bytes per record on the hard drive.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Die &lt;strong&gt;minimale Datensatzgröße&lt;/strong&gt; ist daher in der Tat &lt;strong&gt;9 Bytes&lt;/strong&gt;. Der &lt;strong&gt;zweitgrößte Datensatz&lt;/strong&gt; ist jedoch auch &lt;strong&gt;9 Bytes&lt;/strong&gt;. :-D&lt;/p&gt;
&lt;p&gt;Dabei darf beliebig gewählt werden zwischen 2 Spalten à 1 Byte oder 1 Spalte à 2 Bytes :-)&lt;br /&gt; Daher die Liste:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;The &lt;strong&gt;minimal record size&lt;/strong&gt; is thus in fact &lt;strong&gt;9 bytes&lt;/strong&gt;. The &lt;strong&gt;second biggest record&lt;/strong&gt;, however, is also &lt;strong&gt;9 bytes&lt;/strong&gt;. :-D&lt;/p&gt;
&lt;p&gt;Here, one may freely choose between 2 columns à 1 byte or 1 column à 2 bytes :-).&lt;br /&gt;Hence the list:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;bit&lt;/li&gt;
&lt;li&gt;char(1)&lt;/li&gt;
&lt;li&gt;binary(1)&lt;/li&gt;
&lt;li&gt;tinyint&lt;/li&gt;
&lt;li&gt;char(2)&lt;/li&gt;
&lt;li&gt;nchar(1)&lt;/li&gt;
&lt;li&gt;binary(2)&lt;/li&gt;
&lt;li&gt;smallint&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Kommen wir nun zu &lt;strong&gt;Part 2&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wie viele Datensätze passen maximal auf eine Datenseite&lt;/strong&gt;, wenn wir jetzt wissen, dass jeder Datensatz mindestens 9 Bytes + Offset benötigt?&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Let us now look at &lt;strong&gt;Part 2&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How many records fit maximally on a data page&lt;/strong&gt; if we now know that every data set requires a minimum of 9 bytes + offset?&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Wir testen mit einer Tabelle, bestehend aus einer Spalte mit Datentyp &lt;em&gt;tinyint&lt;/em&gt; – wohlwissend, dass es dasselbe Ergebnis bringen würde, wenn wir &lt;em&gt;smallint&lt;/em&gt; oder etwas anderes aus der Liste oben nehmen würden.&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;We are testing with one table of one column with datatype &lt;em&gt;tinyint&lt;/em&gt; – knowing full well that it would have the same outcome if we were to take &lt;em&gt;smallint&lt;/em&gt; or something else from the list above.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;CREATE TABLE T3_Tinyint&lt;/pre&gt;
&lt;pre&gt;(col tinyint NOT NULL)&lt;/pre&gt;
&lt;pre&gt;GO&lt;/pre&gt;
&lt;pre&gt;…Insert 700 Rows…&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Sehen wir uns an, wie voll die Datenseite geworden ist, und welche Page_ID diese hat:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Then, we will check again how full the data page has become, and which Page_ID it has:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Row_Per_Page_Stage1_700.png&quot; alt=&quot;Row_Per_Page_Stage1_700&quot; width=&quot;813&quot; height=&quot;438&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Ausgehend davon, &lt;strong&gt;dass eine Datenseite 8192 Bytes&lt;/strong&gt; groß ist und abzüglich Header &lt;strong&gt;8096 Bytes für Daten&lt;/strong&gt; zur Verfügung stehen, bedeutet ein Füllgrad von ~95,107%, das noch gut ~396 Bytes zur Verfügung stehen. Durch 11 ergibt das 36. - 36 Datensätze haben also noch Platz!&lt;/p&gt;
&lt;p&gt;Was sagt &lt;strong&gt;&lt;em&gt;DBCC Page&lt;/em&gt;&lt;/strong&gt; dazu?&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Based on the fact that &lt;strong&gt;a data page is 8192 bytes&lt;/strong&gt; in size and that, less the header, &lt;strong&gt;8096 bytes are available for data&lt;/strong&gt;, a fill degree of ~95,107% means that some ~396 are still available. Divided by 11 this equals 36 – there is still room for 36 records!&lt;/p&gt;
&lt;p&gt;What does &lt;strong&gt;&lt;em&gt;DBCC Page&lt;/em&gt;&lt;/strong&gt; have to say to this?&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_DBCCPage_Row_Per_Page_Stage1_700_Page_Header.png&quot; alt=&quot;DBCCPage_Row_Per_Page_Stage1_700_Page_Header&quot; width=&quot;807&quot; height=&quot;566&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Auch hier:&lt;strong&gt; 396 Bytes frei&lt;/strong&gt; – na dann war unsere Überschlagsrechnung gar nicht so schlecht. :-)&lt;/p&gt;
&lt;p&gt;Das heißt &lt;span style=&quot;text-decoration: underline;&quot;&gt;rein rechnerisch müssten weitere 36 Datensätze auf die Seite passen&lt;/span&gt;.&lt;br /&gt; Also „rauf damit“.&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;&lt;strong&gt;396 bytes free &lt;/strong&gt;– well, then, our back-of-the-envelope calculation wasn’t so bad at all. :-)&lt;/p&gt;
&lt;p&gt;That is to say that &lt;span style=&quot;text-decoration: underline;&quot;&gt;in purely arithmetical terms, a further 36 records should fit on the page&lt;/span&gt;.&lt;br /&gt;So “let’s put them on.”&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;pre&gt;…Insert 36 Rows…&lt;/pre&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Row_Per_Page_Stage2_2Pages.png&quot; alt=&quot;Row_Per_Page_Stage2_2Pages&quot; width=&quot;815&quot; height=&quot;474&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;2 Seiten, direkt ab dem 701. Datensatz.&lt;br /&gt; Was ist da los?&lt;br /&gt; Im Hex Editor betrachten wir „das Grauen“:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;2 pages, directly from the 701&lt;sup&gt;st&lt;/sup&gt; data set.&lt;br /&gt;What is going on there?&lt;br /&gt;In the hex editor, we are looking at “the horror”:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Tab_Footer_Offset_FreeSpace_hex.png&quot; alt=&quot;Tab_Footer_Offset_FreeSpace_hex&quot; width=&quot;800&quot; height=&quot;442&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Freier Platz! – Fragmentierung, „Igitt“ ;-)&lt;br /&gt;Was machen wir da?&lt;br /&gt; Ein &lt;strong&gt;&lt;em&gt;Rebuild&lt;/em&gt;&lt;/strong&gt; der Tabelle, was sonst.&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Free space! – Fragmentation, „yuck“ ;-)&lt;br /&gt;What to do?&lt;br /&gt;A &lt;strong&gt;&lt;em&gt;rebuild&lt;/em&gt;&lt;/strong&gt; of the table, what else.&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Row_Per_Page_Stage3_736.png&quot; alt=&quot;Row_Per_Page_Stage3_736&quot; width=&quot;814&quot; height=&quot;295&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Und schon ist die Seite zu glatten 100% gefüllt: 736 Datensätze.&lt;br /&gt; Und das sagt der Header:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;And just like that, the page is filled with a sleek 100%: 736 records.&lt;br /&gt;And this is what the header says:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_DBCCPage_Row_Per_Page_Stage3_736_Page_Header.png&quot; alt=&quot;DBCCPage_Row_Per_Page_Stage3_736_Page_Header&quot; width=&quot;792&quot; height=&quot;451&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Ja, die Page_ID ist eine andere – aber nicht, weil ich gemogelt hätte, sondern weil die Storage Engine für den Rebuild neuen Platz reserviert, und den alten nach getaner Arbeit freigegeben hat.&lt;/p&gt;
&lt;p&gt;Und auch auf Platte sieht es jetzt so aus, wie es sein sollte – bis zum Ende aufgefüllt:&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Yes, the Page_ID is a different one – but not because I might have cheated, but because the storage engine allocated new space for the rebuild, and released the old one after the done work.&lt;/p&gt;
&lt;p&gt;On the drive, too, it now looks exactly how it’s supposed to – filled up to the end:&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt; &lt;img src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Tab_Footer_Offset_Full_hex.png&quot; alt=&quot;Tab_Footer_Offset_Full_hex&quot; width=&quot;800&quot; height=&quot;455&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;Übrigens: Wenn ich anstelle der &lt;em&gt;Heap&lt;/em&gt;-Speicherung der Tabelle einen &lt;em&gt;Clustered Index&lt;/em&gt; als Struktur gewählt hätte, wären die Daten in den allermeisten Fällen sofort auf der einen Seite zu 100% abgelegt worden&lt;br /&gt; – aber was tut man nicht alles für die Spannungskurve :-)&lt;/p&gt;
&lt;p&gt;Ansonsten gilt auch hier die Regel: „Niemals auf etwas verlassen, was man nicht selbst getestet hat“ ;-)&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;By the way, had I chosen a &lt;em&gt;Clustered Index&lt;/em&gt; as structure instead of the &lt;em&gt;Heap&lt;/em&gt;-storage, in most cases, the data would have been stored immediately to a 100% on the one page &lt;br /&gt; – but what’s the fun in that! :-)&lt;/p&gt;
&lt;p&gt;Otherwise, the rule also applies here: “Never rely on something you haven’t tested yourself” ;-)&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;&lt;strong&gt;Ergebnis:&lt;/strong&gt;&lt;br /&gt;Die Antwort auf die Frage lautet daher nicht 700, nicht 732, oder gar 809, sondern: &lt;strong&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;736&lt;/span&gt; Datensätze passen maximal auf eine Seite&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;- und dabei macht es noch nicht einmal einen Unterschied, ob man eine Spalte mit 1 oder 2 Bytes Größe, oder gar 2 Spalten mit je einem Byte Größe verwendet.&lt;/p&gt;
&lt;p&gt;Da jeder Datensatz 9 Bytes zzgl. 2 Bytes Record Offset benötigt, haben wir damit die maximale Kapazität einer SQL Server Datenseite mit 8096 Bytes exakt ausgereizt! :-)&lt;/p&gt;
&lt;p&gt;- Nicht zu verwechseln mit der &lt;em&gt;maximalen Zeilenlänge von 8060 Bytes. &lt;/em&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td valign=&quot;top&quot; width=&quot;334&quot;&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br /&gt;The answer to this question, therefore, is not 700, not 732, or even 809, but: a maximum of &lt;strong&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;736&lt;/span&gt; data records fits on one page&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;- and it does not even make a difference, if one uses one column with 1 or 2 bytes in size, or even 2 columns with one byte in size.&lt;/p&gt;
&lt;p&gt;Since every data record uses 9 bytes plus 2 bytes record offset we will have exactly exhausted the maximum capacity of an SQL Server data page with 8096 bytes! :-)&lt;/p&gt;
&lt;p&gt;- Not to be confused with the &lt;em&gt;maximal row length of 8060 bytes.&lt;/em&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;my nine bytes&lt;/p&gt;
&lt;p&gt;Andreas&lt;/p&gt;</description>
			<content:encoded><![CDATA[<p>Maximale Anzahl Zeilen je Datenseite und minimale Datensatzgröße</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>(DE)<br /> In einer meiner letzten Master-Classes tauchte die nicht ganz ernste aber dennoch interessante Fragestellung auf:</p>
<p>Wie viele Zeilen passen eigentlich maximal auf eine Datenseite? – wenn die Datensätze/Records so klein wie möglich sind.</p>
<p>Zunächst, <strong>Part 1</strong>, was ist der kleinstmögliche Datensatz in SQL Server?</p>
<p>Um das zu beurteilen, ist es gut, die Datentypen sowie die Struktur eines Datensatzes genau zu kennen.<br /> Man könnte versucht sein, anzunehmen, dass eine Spalte vom Datentyp <em>bit</em> der kleinstmögliche Datensatz ist. Der erfahrene SQL‘er wird wissen, dass ein <em>bit</em> allein auch immer mindestens 1 <em>byte</em> in einem Record benötigt – erst bei mehreren Spalten dieses Datentyps, kommt ein Platzersparnis ins Spiel (<a href="http://msdn.microsoft.com/de-de/library/ms177603.aspx" target="_blank">bit (Transact-SQL)</a>).</p>
<p>Der nächste Kandidat sind Datentypen, die laut der <a href="http://msdn.microsoft.com/de-de/library/ms187752.aspx" target="_blank">Liste in Books Online</a> nur <strong>1 byte</strong> Speicherplatz benötigen. Das wären folgende:</p>
</td>
<td valign="top" width="334">
<p>(EN)<br /> In one of my last Master classes, a not quite so serious but nevertheless interesting question was brought up:</p>
<p>How many rows maximally do actually fit on a data page? – if the data sets/records are as small as possible.</p>
<p>First of all, <strong>part 1</strong>, what is the smallest possible data set in SQL Server?</p>
<p>In order to assess this, it is commendable to know exactly the data types as well as the structure of a data set. </p>
<p>One could be tempted to assume that a column of the data type <em>bit</em> is the smallest possible data set. The experienced SQL people will know that a <em>bit</em> alone always also requires at least 1 <em>byte</em> in one record – only with several columns of this data type, the place-saving aspect comes into play (<a href="http://msdn.microsoft.com/en-us/library/ms177603.aspx" target="_blank">bit (Transact-SQL)</a>).</p>
<p>The next candidate are data types which according to the <a href="http://msdn.microsoft.com/en-us/library/ms187752.aspx" target="_blank">list in Books Online</a> use only <strong>1 byte</strong> of storage. These would be the following:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<ul>
<li>bit</li>
<li>char(1)</li>
<li>binary(1)</li>
<li>tinyint</li>
</ul>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Tatsächlich benötigen <span style="text-decoration: underline;">in diesem besonderen Fall</span>, <strong>einer einzigen Spalte je Datensatz</strong>, auch Records mit Nettowert von 2 Bytes, <strong>9 Bytes</strong> auf der Datenseite:</p>
</td>
<td valign="top" width="334">
<p>As a matter of fact, <span style="text-decoration: underline;">in this particular case</span> of <strong>a single column per record</strong>, also records with a net value of 2 bytes use <strong>9 bytes</strong> on the data page:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<ul>
<li>char(2)</li>
<li>nchar(1)</li>
<li>binary(2)</li>
<li>smallint</li>
</ul>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Wie kommt das?<br /> Das liegt an der Struktur der Datensätze. Diese ist hinlänglich in diversen Blogs dokumentiert (z.B. hier <a href="http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-record/" target="_blank">Inside the Storage Engine: Anatomy of a record</a> und hier: <a href="https://www.simple-talk.com/sql/database-administration/sql-server-storage-internals-101/" target="_blank">SQL Server Storage Internals 101</a> ), jedoch eher für allgemeine Zwecke und dieser Sonderfall (eine 1-byte-Spalte) ist dabei weniger im Fokus.</p>
<p>Theoretisch würden für einen Datensatz 8 Bytes ausreichen:</p>
<p>4 Bytes: Datensatzkopf (Typ + Zeiger auf Null-Bitmap)<br />1 Byte: Daten<br />2 Bytes: Anzahl der Spalten im Record<br />1 Byte: NULL Bitmap</p>
<p>Dazu kommt noch der 2 Bytes große Zeiger im Page-Offset, was dann 10 Bytes ergeben würde.<br />Dennoch belegt ein solcher Datensatz 9 Bytes auf der Seite/Page + Offset.</p>
<p>Woran das liegt, sehen wir uns an.</p>
</td>
<td valign="top" width="334">
<p>How come?<br />This has to do with the structure of the data sets, which is sufficiently documented in various blogs (e.g. here: <a href="http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-record/" target="_blank">Inside the Storage Engine: Anatomy of a record</a> and here: <a href="https://www.simple-talk.com/sql/database-administration/sql-server-storage-internals-101/" target="_blank">SQL Server Storage Internals 101</a> ), but rather for general purposes, and this special case (a 1-byte-column) is less focused on here.</p>
<p>Theoretically, 8 bytes would be sufficient for a data set:</p>
<p>4 bytes: data set head (type + pointer to NULL-bitmap)<br />1 byte: data<br />2 bytes: number of columns in record<br />1 byte: NULL bitmap</p>
<p>Add to that the 2-bytes-pointer in the page offset, which would then result in 10 bytes.<br />Despite this, such a data set uses 9 bytes on the page/page + offset.</p>
<p>We will now look at the reason for this.</p>
</td>
</tr>
<tr>
<td valign="top" width="334">
<p>Im Folgenden definiere ich 2 Tabellen mit jeweils einer bzw. 2 Spalten von Datentyp <em>tinyint</em>, der ja bekanntlich einen Byte benötigt:</p>
</td>
<td valign="top" width="334">
<p>In the following, I am defining 2 tables with one and 2 columns each of the data type <em>tinyint</em>, which is known to use 1 byte:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<pre>CREATE TABLE T1col</pre>
<pre>(col1 tinyint null)</pre>
<pre>GO</pre>
<pre>CREATE TABLE T2col</pre>
<pre>(col1 tinyint null, col2 tinyint null)</pre>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Danach füge ich zuerst Datenätze mit dem Wert „255“ bzw „255, 255“ ein, und danach einige mit Wert „NULL“.</p>
<p>Mit DBCC Page kann man sich den Header der Datenseiten beider Tabellen ansehen, und findet eine kleine Überraschung (Ergebnis reduziert):</p>
</td>
<td valign="top" width="334">
<p>Next, I am inserting, first, data set of the value “255” or “255, 255” and then a few of the value “NULL.”</p>
<p>With the DBCC page, one can look at the header of the data pages of both tables, and one will find a small surprise (reduced result). </p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p> <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_DBCCPage_1vs2cols.png" alt="DBCCPage_1vs2cols" width="767" height="801" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Obwohl die Größe der Daten fixer Länge (<em>pminlen</em>) mit 5 bzw. 6 unterschiedlich angegeben wird, ist der freie Speicherplatz auf der Seite (<em>m_freeCnt</em>) identisch! (<em>rot</em>)</p>
<p>Der Datensatz belegt in beiden Fällen jedoch 9 Bytes im Page-body (<em>blau</em>).</p>
<p>So sieht die Tabelle, bestehend aus <span style="text-decoration: underline;">einer Spalte</span>, mit einigen Datensätzen gefüllt, auf der Festplatte aus:</p>
</td>
<td valign="top" width="334">
<p>Even though the size of the fixed-length data (<em>pminlen</em>) is specified differently, with 5 and 6 respectively, the free storage on the page (<em>m_freeCnt</em>) is identical! (<em>red</em>)</p>
<p>The record, however, uses in both cases 9 bytes in the page body. (<em>blue</em>)</p>
<p>This is what the table, consisting of <span style="text-decoration: underline;">one column</span>, filled up with a few records, looks like on the hard drive:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p>  <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Page_Record_1col9byte_hex.png" alt="Page_Record_1col9byte_hex" width="989" height="157" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Man sieht, dass 9 Bytes belegt sind, jedoch nur, da nach der NULL Bitmap noch ein Byte jedem Datensatz anhängig ist (<em>gelb</em> markiert).</p>
<p>Hier die Tabelle mit <span style="text-decoration: underline;">2 Spalten</span>:</p>
</td>
<td valign="top" width="334">
<p>One can see that 9 bytes are used, but only because after the NULL bitmap, one extra byte is attached to each data set (marked in <em>yellow</em>).</p>
<p>Below, see the table with 2 columns:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p> <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Page_Record_2cols9byte_hex.png" alt="1410_Page_Record_2cols9byte_hex.png" width="985" height="153" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Auch hier also 9 Bytes, mit dem Unterschied, wie das letzte Byte verwendet wird.</p>
<p>Noch etwas deutlicher wird es im Binärformat. Das ist die Tabelle mit 2 Spalten – auch diese benötigt 9 Bytes, und man sieht unten, wie die NULL Bitmap zu ihrem Namen kommt:</p>
</td>
<td valign="top" width="334">
<p>Here, too, it is 9 bytes, with the difference being how the last byte is used.</p>
<p>It becomes a bit clearer in the binary format.<br />This is the table with 2 columns –this one uses 9 bytes as well, and you can see below how the NULL bitmap gets its name:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p><img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Page_Record_2cols9byte_binary.png" alt="Page_Record_2cols9byte_binary" width="749" height="231" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Dieser eine Byte, der für mich keinen klaren Nutzen hat, führt also zu dem Ergebnis, das beide Tabellen letztlich 9 Bytes je Record auf der Festplatte benötigen.</p>
</td>
<td valign="top" width="334">
<p>This one byte, which to me does not have any clear purpose, is what leads to the result that both tables ultimately use 9 bytes per record on the hard drive.</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Die <strong>minimale Datensatzgröße</strong> ist daher in der Tat <strong>9 Bytes</strong>. Der <strong>zweitgrößte Datensatz</strong> ist jedoch auch <strong>9 Bytes</strong>. :-D</p>
<p>Dabei darf beliebig gewählt werden zwischen 2 Spalten à 1 Byte oder 1 Spalte à 2 Bytes :-)<br /> Daher die Liste:</p>
</td>
<td valign="top" width="334">
<p>The <strong>minimal record size</strong> is thus in fact <strong>9 bytes</strong>. The <strong>second biggest record</strong>, however, is also <strong>9 bytes</strong>. :-D</p>
<p>Here, one may freely choose between 2 columns à 1 byte or 1 column à 2 bytes :-).<br />Hence the list:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<ul>
<li>bit</li>
<li>char(1)</li>
<li>binary(1)</li>
<li>tinyint</li>
<li>char(2)</li>
<li>nchar(1)</li>
<li>binary(2)</li>
<li>smallint</li>
</ul>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Kommen wir nun zu <strong>Part 2</strong>:</p>
<p><strong>Wie viele Datensätze passen maximal auf eine Datenseite</strong>, wenn wir jetzt wissen, dass jeder Datensatz mindestens 9 Bytes + Offset benötigt?</p>
</td>
<td valign="top" width="334">
<p>Let us now look at <strong>Part 2</strong>:</p>
<p><strong>How many records fit maximally on a data page</strong> if we now know that every data set requires a minimum of 9 bytes + offset?</p>
</td>
</tr>
<tr>
<td valign="top" width="334">
<p>Wir testen mit einer Tabelle, bestehend aus einer Spalte mit Datentyp <em>tinyint</em> – wohlwissend, dass es dasselbe Ergebnis bringen würde, wenn wir <em>smallint</em> oder etwas anderes aus der Liste oben nehmen würden.</p>
</td>
<td valign="top" width="334">
<p>We are testing with one table of one column with datatype <em>tinyint</em> – knowing full well that it would have the same outcome if we were to take <em>smallint</em> or something else from the list above.</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<pre>CREATE TABLE T3_Tinyint</pre>
<pre>(col tinyint NOT NULL)</pre>
<pre>GO</pre>
<pre>…Insert 700 Rows…<br /><br /></pre>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Sehen wir uns an, wie voll die Datenseite geworden ist, und welche Page_ID diese hat:</p>
</td>
<td valign="top" width="334">
<p>Then, we will check again how full the data page has become, and which Page_ID it has:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p> <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Row_Per_Page_Stage1_700.png" alt="Row_Per_Page_Stage1_700" width="813" height="438" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Ausgehend davon, <strong>dass eine Datenseite 8192 Bytes</strong> groß ist und abzüglich Header <strong>8096 Bytes für Daten</strong> zur Verfügung stehen, bedeutet ein Füllgrad von ~95,107%, das noch gut ~396 Bytes zur Verfügung stehen. Durch 11 ergibt das 36. - 36 Datensätze haben also noch Platz!</p>
<p>Was sagt <strong><em>DBCC Page</em></strong> dazu?</p>
</td>
<td valign="top" width="334">
<p>Based on the fact that <strong>a data page is 8192 bytes</strong> in size and that, less the header, <strong>8096 bytes are available for data</strong>, a fill degree of ~95,107% means that some ~396 are still available. Divided by 11 this equals 36 – there is still room for 36 records!</p>
<p>What does <strong><em>DBCC Page</em></strong> have to say to this?</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p> <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_DBCCPage_Row_Per_Page_Stage1_700_Page_Header.png" alt="DBCCPage_Row_Per_Page_Stage1_700_Page_Header" width="807" height="566" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Auch hier:<strong> 396 Bytes frei</strong> – na dann war unsere Überschlagsrechnung gar nicht so schlecht. :-)</p>
<p>Das heißt <span style="text-decoration: underline;">rein rechnerisch müssten weitere 36 Datensätze auf die Seite passen</span>.<br /> Also „rauf damit“.</p>
</td>
<td valign="top" width="334">
<p><strong>396 bytes free </strong>– well, then, our back-of-the-envelope calculation wasn’t so bad at all. :-)</p>
<p>That is to say that <span style="text-decoration: underline;">in purely arithmetical terms, a further 36 records should fit on the page</span>.<br />So “let’s put them on.”</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<pre>…Insert 36 Rows…</pre>
<p> </p>
<p><img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Row_Per_Page_Stage2_2Pages.png" alt="Row_Per_Page_Stage2_2Pages" width="815" height="474" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>2 Seiten, direkt ab dem 701. Datensatz.<br /> Was ist da los?<br /> Im Hex Editor betrachten wir „das Grauen“:</p>
</td>
<td valign="top" width="334">
<p>2 pages, directly from the 701<sup>st</sup> data set.<br />What is going on there?<br />In the hex editor, we are looking at “the horror”:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p> <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Tab_Footer_Offset_FreeSpace_hex.png" alt="Tab_Footer_Offset_FreeSpace_hex" width="800" height="442" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Freier Platz! – Fragmentierung, „Igitt“ ;-)<br />Was machen wir da?<br /> Ein <strong><em>Rebuild</em></strong> der Tabelle, was sonst.</p>
</td>
<td valign="top" width="334">
<p>Free space! – Fragmentation, „yuck“ ;-)<br />What to do?<br />A <strong><em>rebuild</em></strong> of the table, what else.</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p><img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Row_Per_Page_Stage3_736.png" alt="Row_Per_Page_Stage3_736" width="814" height="295" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Und schon ist die Seite zu glatten 100% gefüllt: 736 Datensätze.<br /> Und das sagt der Header:</p>
</td>
<td valign="top" width="334">
<p>And just like that, the page is filled with a sleek 100%: 736 records.<br />And this is what the header says:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p> <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_DBCCPage_Row_Per_Page_Stage3_736_Page_Header.png" alt="DBCCPage_Row_Per_Page_Stage3_736_Page_Header" width="792" height="451" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Ja, die Page_ID ist eine andere – aber nicht, weil ich gemogelt hätte, sondern weil die Storage Engine für den Rebuild neuen Platz reserviert, und den alten nach getaner Arbeit freigegeben hat.</p>
<p>Und auch auf Platte sieht es jetzt so aus, wie es sein sollte – bis zum Ende aufgefüllt:</p>
</td>
<td valign="top" width="334">
<p>Yes, the Page_ID is a different one – but not because I might have cheated, but because the storage engine allocated new space for the rebuild, and released the old one after the done work.</p>
<p>On the drive, too, it now looks exactly how it’s supposed to – filled up to the end:</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p> <img src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1410_Tab_Footer_Offset_Full_hex.png" alt="Tab_Footer_Offset_Full_hex" width="800" height="455" /></p>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p>Übrigens: Wenn ich anstelle der <em>Heap</em>-Speicherung der Tabelle einen <em>Clustered Index</em> als Struktur gewählt hätte, wären die Daten in den allermeisten Fällen sofort auf der einen Seite zu 100% abgelegt worden<br /> – aber was tut man nicht alles für die Spannungskurve :-)</p>
<p>Ansonsten gilt auch hier die Regel: „Niemals auf etwas verlassen, was man nicht selbst getestet hat“ ;-)</p>
</td>
<td valign="top" width="334">
<p>By the way, had I chosen a <em>Clustered Index</em> as structure instead of the <em>Heap</em>-storage, in most cases, the data would have been stored immediately to a 100% on the one page <br /> – but what’s the fun in that! :-)</p>
<p>Otherwise, the rule also applies here: “Never rely on something you haven’t tested yourself” ;-)</p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="334">
<p><strong>Ergebnis:</strong><br />Die Antwort auf die Frage lautet daher nicht 700, nicht 732, oder gar 809, sondern: <strong><span style="text-decoration: underline;">736</span> Datensätze passen maximal auf eine Seite</strong>.</p>
<p>- und dabei macht es noch nicht einmal einen Unterschied, ob man eine Spalte mit 1 oder 2 Bytes Größe, oder gar 2 Spalten mit je einem Byte Größe verwendet.</p>
<p>Da jeder Datensatz 9 Bytes zzgl. 2 Bytes Record Offset benötigt, haben wir damit die maximale Kapazität einer SQL Server Datenseite mit 8096 Bytes exakt ausgereizt! :-)</p>
<p>- Nicht zu verwechseln mit der <em>maximalen Zeilenlänge von 8060 Bytes. </em></p>
</td>
<td valign="top" width="334">
<p><strong>Result:</strong><br />The answer to this question, therefore, is not 700, not 732, or even 809, but: a maximum of <strong><span style="text-decoration: underline;">736</span> data records fits on one page</strong>.</p>
<p>- and it does not even make a difference, if one uses one column with 1 or 2 bytes in size, or even 2 columns with one byte in size.</p>
<p>Since every data record uses 9 bytes plus 2 bytes record offset we will have exactly exhausted the maximum capacity of an SQL Server data page with 8096 bytes! :-)</p>
<p>- Not to be confused with the <em>maximal row length of 8060 bytes.</em></p>
</td>
</tr>
</tbody>
</table>
<p> </p>
<p>my nine bytes</p>
<p>Andreas</p>]]></content:encoded>
								<comments>https://www.insidesql.org/blogs/andreaswolter/2014/10/maximale-anzahl-zeilen-je-datenseite-max-row-data-page-in-sql-server#comments</comments>
			<wfw:commentRss>https://www.insidesql.org/blogs/andreaswolter/?tempskin=_rss2&#38;disp=comments&#38;p=3740</wfw:commentRss>
		</item>
				<item>
			<title>Scripting Table Data with SQL Server 2008 R2</title>
			<link>https://www.insidesql.org/blogs/andreaswolter/2010/10/scripting-table-data-with-ssms-sql-server</link>
			<pubDate>Fri, 22 Oct 2010 11:02:00 +0000</pubDate>			<dc:creator>Andreas Wolter</dc:creator>
			<category domain="main">Miscellaneous</category>
<category domain="alt">Scripts</category>			<guid isPermaLink="false">3569@https://www.insidesql.org/blogs/</guid>
						<description>&lt;p&gt;I recently was asked, whether the Feature “Script Data” as T-SQL-command INSERT INTO… has been removed in SQL Server 208 R2.&lt;/p&gt;
&lt;p&gt;In fact, it was not visible on first sight.&lt;/p&gt;
&lt;p&gt;This is how you can find it:&lt;/p&gt;
&lt;p&gt;It is still the right-click “Tasks” - &lt;strong&gt;“Generate Scripts” –Wizard.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After having chosen the Table(s), the following window appears:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.vb-magazin.de/forums/blogs/andreaswolter/image_63746429.png&quot; target=&quot;_blank&quot;&gt;&lt;img title=&quot;SQL_2008R2_Set_Scripting_Options&quot; src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_DB_Scripting_Options.png&quot; alt=&quot;SQL_2008R2_Set_Scripting_Options&quot; width=&quot;414&quot; height=&quot;385&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;there click “Advanced” and scroll down inside the “General”-part until the Element “Types of data” to script&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.vb-magazin.de/forums/blogs/andreaswolter/image_096A1480.png&quot; target=&quot;_blank&quot;&gt;&lt;img title=&quot;image&quot; src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_DB_Advanced_Scripting_Options.png&quot; alt=&quot;DB_Advanced_Scripting_Options&quot; width=&quot;434&quot; height=&quot;591&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And there under the following drop-down, it is hidden:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.vb-magazin.de/forums/blogs/andreaswolter/image_2840885E.png&quot; target=&quot;_blank&quot;&gt;&lt;img title=&quot;Types_of_data_to_script_drop_down&quot; src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_Script_Schema_Only.png&quot; alt=&quot;Types_of_data_to_script_drop_down&quot; width=&quot;212&quot; height=&quot;58&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And the German translation “Datentypen, für die ein Skript erstellt wird”, makes it even harder to detect:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.vb-magazin.de/forums/blogs/andreaswolter/image_4FEA0125.png&quot; target=&quot;_blank&quot;&gt;&lt;img title=&quot;Erweitere_Skriptoptionen&quot; src=&quot;http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_Script_Nur_Schema.png&quot; alt=&quot;Erweitere_Skriptoptionen&quot; width=&quot;378&quot; height=&quot;182&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Conclusion: Scripting out Data with “INSERT INTO”-commands is a bit hidden – (under SQL 2008 it was under the “Table/View Options”, now under “General” – “Types of data to script”) but still available :-)&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.andreas-wolter.com&quot; target=&quot;_blank&quot;&gt;www.andreas-wolter.com&lt;/a&gt;&lt;/p&gt;</description>
			<content:encoded><![CDATA[<p>I recently was asked, whether the Feature “Script Data” as T-SQL-command INSERT INTO… has been removed in SQL Server 208 R2.</p>
<p>In fact, it was not visible on first sight.</p>
<p>This is how you can find it:</p>
<p>It is still the right-click “Tasks” - <strong>“Generate Scripts” –Wizard.</strong></p>
<p>After having chosen the Table(s), the following window appears:</p>
<p><a href="http://www.vb-magazin.de/forums/blogs/andreaswolter/image_63746429.png" target="_blank"><img title="SQL_2008R2_Set_Scripting_Options" src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_DB_Scripting_Options.png" alt="SQL_2008R2_Set_Scripting_Options" width="414" height="385" border="0" /></a></p>
<p>there click “Advanced” and scroll down inside the “General”-part until the Element “Types of data” to script</p>
<p><a href="http://www.vb-magazin.de/forums/blogs/andreaswolter/image_096A1480.png" target="_blank"><img title="image" src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_DB_Advanced_Scripting_Options.png" alt="DB_Advanced_Scripting_Options" width="434" height="591" border="0" /></a></p>
<p>And there under the following drop-down, it is hidden:</p>
<p><a href="http://www.vb-magazin.de/forums/blogs/andreaswolter/image_2840885E.png" target="_blank"><img title="Types_of_data_to_script_drop_down" src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_Script_Schema_Only.png" alt="Types_of_data_to_script_drop_down" width="212" height="58" border="0" /></a></p>
<p>And the German translation “Datentypen, für die ein Skript erstellt wird”, makes it even harder to detect:</p>
<p><a href="http://www.vb-magazin.de/forums/blogs/andreaswolter/image_4FEA0125.png" target="_blank"><img title="Erweitere_Skriptoptionen" src="http://www.sarpedonqualitylab.com/sql-images/sql-articles/1010_Script_Nur_Schema.png" alt="Erweitere_Skriptoptionen" width="378" height="182" border="0" /></a></p>
<p>Conclusion: Scripting out Data with “INSERT INTO”-commands is a bit hidden – (under SQL 2008 it was under the “Table/View Options”, now under “General” – “Types of data to script”) but still available :-)</p>
<p> </p>
<p><a href="http://www.andreas-wolter.com" target="_blank">www.andreas-wolter.com</a></p>]]></content:encoded>
								<comments>https://www.insidesql.org/blogs/andreaswolter/2010/10/scripting-table-data-with-ssms-sql-server#comments</comments>
			<wfw:commentRss>https://www.insidesql.org/blogs/andreaswolter/?tempskin=_rss2&#38;disp=comments&#38;p=3569</wfw:commentRss>
		</item>
			</channel>
</rss>
