<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rollback &#187; index</title>
	<atom:link href="http://blog.rollback.hu/tag/index/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.rollback.hu</link>
	<description>SQL, üzemeltetés kicsiknek és nagyoknak.</description>
	<lastBuildDate>Thu, 17 Nov 2011 16:38:59 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Indexek, amiket a kutya sem használ</title>
		<link>http://blog.rollback.hu/2009/10/indexek-amiket-a-kutya-sem-hasznal/</link>
		<comments>http://blog.rollback.hu/2009/10/indexek-amiket-a-kutya-sem-hasznal/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 14:36:04 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[database engine]]></category>
		<category><![CDATA[DMV]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[üzemeltetés]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=117</guid>
		<description><![CDATA[(apró technikai malőr miatt a táblázat pillanatnyilag bebújik a sidebar mögé, bocs, legjobb embereink dolgoznak a hiba elhárításán)
Az egyik nagy jósága a SQL 2005+ szervernek, hogy megmutatja az indexek ki(nem)használtságát, illetve elmondja, hogy milyen jelenleg nemlétező index mekkora hasznot hozna. Ezeket természetesen DMV-ken keresztül teszi meg velünk. 
Az indexeink kihasználtságát a sys.dm_db_index_usage_stats DMV mutatja meg, [...]]]></description>
			<content:encoded><![CDATA[<p>(apró technikai malőr miatt a táblázat pillanatnyilag bebújik a sidebar mögé, bocs, legjobb embereink dolgoznak a hiba elhárításán)</p>
<p>Az egyik nagy jósága a SQL 2005+ szervernek, hogy megmutatja az indexek ki(nem)használtságát, illetve elmondja, hogy milyen jelenleg nemlétező index mekkora hasznot hozna. Ezeket természetesen DMV-ken keresztül teszi meg velünk. </p>
<p>Az indexeink kihasználtságát a sys.dm_db_index_usage_stats DMV mutatja meg, egy kis minta így néz ki belőle:</p>
<pre class="brush: sql;">
SELECT top 3 * FROM sys.dm_db_index_usage_stats
WHERE object_id &gt; 255
</pre>
<p>Az erősen irányított válasz pedig<br />
<table id="wp-table-reloaded-id-6-no-1" class="wp-table-reloaded wp-table-reloaded-id-6" cellspacing="1" cellpadding="1" border="1">
<thead>
	<tr class="odd row-1">
		<th class="column-1">database_id</th><th class="column-2">object_id</th><th class="column-3">index_id</th><th class="column-4">user_seeks</th><th class="column-5">user_scans</th><th class="column-6">user_lookups</th><th class="column-7">user_updates</th><th class="column-8">last_user_seek</th><th class="column-9">last_user_scan</th><th class="column-10">last_user_lookup</th><th class="column-11">last_user_update</th><th class="column-12">system_seeks</th><th class="column-13">system_scans</th><th class="column-14">system_lookups</th><th class="column-15">system_updates</th><th class="column-16">last_system_seek</th><th class="column-17">last_system_scan</th><th class="column-18">last_system_lookup</th><th class="column-19">last_system_update</th>
	</tr>
</thead>
<tbody>
	<tr class="even row-2">
		<td class="column-1">5</td><td class="column-2">709577566</td><td class="column-3">2</td><td class="column-4">3</td><td class="column-5">3456</td><td class="column-6">0</td><td class="column-7">2154356</td><td class="column-8">NULL</td><td class="column-9">2009.10.18 15:46</td><td class="column-10">NULL</td><td class="column-11">2009-10-18 16:00:37.097</td><td class="column-12">0</td><td class="column-13">34</td><td class="column-14">0</td><td class="column-15">0</td><td class="column-16">NULL</td><td class="column-17">2009-10-18 01:00:23.000</td><td class="column-18">NULL</td><td class="column-19">NULL</td>
	</tr>
	<tr class="odd row-3">
		<td class="column-1">5</td><td class="column-2">709577566</td><td class="column-3">1</td><td class="column-4">2154356</td><td class="column-5">0</td><td class="column-6">2154356</td><td class="column-7">2154356</td><td class="column-8">2009-10-18 16:00:37.097</td><td class="column-9">NULL</td><td class="column-10">2009-10-18 16:00:37.097</td><td class="column-11">2009-10-18 16:00:37.097</td><td class="column-12">0</td><td class="column-13">34</td><td class="column-14">0</td><td class="column-15">0</td><td class="column-16">NULL</td><td class="column-17">2009-10-18 01:00:23.000</td><td class="column-18">NULL</td><td class="column-19">NULL</td>
	</tr>
	<tr class="even row-4">
		<td class="column-1">5</td><td class="column-2">709577566</td><td class="column-3">3</td><td class="column-4">0</td><td class="column-5">0</td><td class="column-6">0</td><td class="column-7">2154356</td><td class="column-8">NULL</td><td class="column-9">NULL</td><td class="column-10">NULL</td><td class="column-11">2009-10-18 16:00:37.097</td><td class="column-12">0</td><td class="column-13">34</td><td class="column-14">0</td><td class="column-15">0</td><td class="column-16">NULL</td><td class="column-17">2009-10-18 01:00:23.000</td><td class="column-18">NULL</td><td class="column-19">NULL</td>
	</tr>
</tbody>
</table>
<br />
Ebből a következőket kell figyelnünk: a db-object-index id-k magukért beszélnek, abból tudjuk, hogy minek is nézzük az adatait. A user seek/scan/lookup és a hozzájuk tartozó last&#8230; oszlopok talán a legfontosabbak, ők mutatják meg a tényleges indexhasználatot. Az user_update oszlop érdekes, az index ugyanis akkor update-elődik, ha a tartalmazott adat változik. Ez az úgynevezett indexkarbantartás, ami kissé drága, ezért nem szeretjük a felesleges indexeket. Merő véletlenségből a fenti minta pont tartalmaz egy ilyen indexet, a 3-as számút (egy tábla három indexének az értékeit választottam ki). Látszik, hogy semmi másra nem használja a szerver az indexet, csak karbantartja, frissítgeti. Ez egy tipikus jó jelölt arra, hogy letörölje az ember fia egy vidám hétfő reggelen, ha elég nagy minta alapján még mindig nulla a három mező összege. Volt szerencsém találkozni olyan indexszel, amit 1.1 milliárdszor kellett update-elnie az engine-nek, és soha nem használta. Lehet azt mondani, hogy nem kér enni, de hát szemmel láthatóan ez nem igaz.</p>
<p>Éles szemű egyének észrevehetik, hogy azért a system_scan oszlop értéke egyáltalán nem nulla. Ez anna kköszönhető, hogy az indexstatisztikák frissítéséhez az SQL szerver scannel. Úgyhogy ezt nem kell feltétlenül figyelembe venni. </p>
<p>Mire jó még ez a használati statisztika? Láthatjuk, hogy user_lookup mindig csak az index_id = 1 indexeken történik, azaz a clustered indexen. Természetes, hiszen a bookmark/key lookup itt szokott történni. Lehet, hogy van rá ellenpélda, de azt most kihagynám. És most keressük meg a legnagyobb user_scan értékű indexeket és a hozzájuk tartozó clustered indexeket: ha nagyon magas a clustered indexen a user_lookup érték is és kicsi a scan, akkor találtunk egy jó ellenjelöltet clustered indexre.</p>
<p>És megint, csak egyetlen DMV a sokból, és milyen sok hasznos dolgot árul el&#8230; Hát nem csodálatos? (nem, a csodálatos az az, hogy három tesztgépre sikerült három különböző SQL verziót/editiont telepítenem, anélkül, hogy észrevettem volna addig, amíg el nem frakkolt a teszt&#8230;)</p>
<p>Visszatérve a címre:</p>
<pre class="brush: sql;">
select * from sys.dm_db_index_usage_stats
where object_id &gt; 255
and user_seeks + user_scans + user_lookups = 0
order by database_id, object_id
</pre>
<p>Ők azok az indexek, akiket a kutya sem használt &#8211; az SQL Server legutóbbi indulása óta. Ez a DMV ugyanis minden szerver restartkor kiürül és újrakezdi a feltöltését a szerver. Tehát ha tegnap óta fut a gép, ne használjuk nagytakarításra az outputot. Tanácsos elmenteni a kimenetet &#8211; én mindennap elmentem egy külön táblába, és ha nem indult újra előző nap óta a szerver, akkor az előző napit meeg kitörlöm. Így csak legfeljebb egy napi statisztikát veszíthetek, de megvan hónapokra visszamenőleg minden.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2009/10/indexek-amiket-a-kutya-sem-hasznal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UNIQUE és több NULL</title>
		<link>http://blog.rollback.hu/2008/05/unique-es-tobb-null/</link>
		<comments>http://blog.rollback.hu/2008/05/unique-es-tobb-null/#comments</comments>
		<pubDate>Sun, 04 May 2008 22:17:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Magyar]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[sql2008]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=9</guid>
		<description><![CDATA[(This article has an  English version&#8230;)
Ha szeretnénk biztosítani azt, hogy egy oszlop értékei mind egyeidek legyenek, akkor használhatjuk a UNIQUE kulcsszót (akár constraint, akár index formában), hogy ezt kierőszakoljuk. Ez eddig szép és jó, de mi a helyzet a NULL értékekkel? Egy NULL-t simán be tudunk szúrni (ez ugye a nagy különbség a UNIQUE [...]]]></description>
			<content:encoded><![CDATA[<p>(This article has an <a href ="http://blog.rollback.hu/2008/04/unique-index-vs-multiple-null/trackback/"> English</a> version&#8230;)<br />
Ha szeretnénk biztosítani azt, hogy egy oszlop értékei mind egyeidek legyenek, akkor használhatjuk a UNIQUE kulcsszót (akár constraint, akár index formában), hogy ezt kierőszakoljuk. Ez eddig szép és jó, de mi a helyzet a NULL értékekkel? Egy NULL-t simán be tudunk szúrni (ez ugye a nagy különbség a UNIQUE és a PRIMARY KEY között, utóbbi nem enged semmilyen NULL-t), de mi van, ha sok NULL-t akarok bepakolni? <span id="more-9"></span> Pl. tároljuk az ügyfelek pénzügyi azonosítóját a különféle ki- és befizetések azonosítására, de vannak ügyfeleink, akikkel nincs ilyen pénzügyi kapcsolatunk. A klasszikus ANSI SQL szerint lehet több NULL egy UNIQUE oszlopban, hiszen NULL &lt;&gt; NULL a definíció szerint. A Microsoft által használt megközelítés meg azt mondja, hogy ha megtalálom az értéket a táblában, akkor az nem lehet egyedi. Lehet vitatkozni a nézőpontokon (azt hiszem, meglepő módon a DB2 is az utóbbit használja), mindenesetre változtatni rajta nemigen lehet. Vannak mindenféle érdekes kerülőutak, de mindenesetre, ez elég bosszantó lehet. Annak, aki nem használ SQL Server 2008-at. A SQL 2008-ban bevezetett filtered index nevű feature lehetőséget biztosít arra, hogy ne az egész táblára, csak annak egy részére készítsük el az indexünket. A szintaktika roppant egyszerű:<br />
Hogyan segít ez rajtunk? Hát, egyszerűen: adjuk hozzá azt a feltételt, hogy csak a nem NULL oszlopokra akarunk UNIQUE indexet készíteni. Rövid példa:</p>
<pre class="brush: sql;">CREATE TABLE tempdb.dbo.t1 (col1 int)
CREATE UNIQUE INDEX IX_t1_col1 on tempdb.dbo.t1 (col1)
WHERE col1 IS NOT NULL
-- dobjunk be par sort...
INSERT INTO tempdb.dbo.t1 VALUES (1),(2),(NULL)
--ez bukta
INSERT INTO tempdb.dbo.t1 VALUES (1)
--ez nem bukta
INSERT INTO tempdb.dbo.t1 VALUES (NULL)</pre>
<p>És tessék, máris Oracle-kompatibilis UNIQUE-or kaptunk. Jó, mi? :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2008/05/unique-es-tobb-null/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UNIQUE INDEX vs multiple NULL values</title>
		<link>http://blog.rollback.hu/2008/04/unique-index-vs-multiple-null/</link>
		<comments>http://blog.rollback.hu/2008/04/unique-index-vs-multiple-null/#comments</comments>
		<pubDate>Fri, 18 Apr 2008 23:55:46 +0000</pubDate>
		<dc:creator>Erik</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[index]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[sql2008]]></category>

		<guid isPermaLink="false">http://blog.rollback.hu/?p=7</guid>
		<description><![CDATA[In Microsoft SQL Server, if you want to make sure that a column contains no duplicates, you can use the UNIQUE keyword to enforce this constraint, either by creating a unique index or by adding a unique constraint to the column. It&#8217;s very useful and nice, but&#8230; What about NULL values? I mean, obviously, you [...]]]></description>
			<content:encoded><![CDATA[<p>In Microsoft SQL Server, if you want to make sure that a column contains no duplicates, you can use the UNIQUE keyword to enforce this constraint, either by creating a unique index or by adding a unique constraint to the column. It&#8217;s very useful and nice, but&#8230; What about NULL values? I mean, obviously, you can insert the first NULL value, but what if you have more null values and you need to enforce only the uniqueness of the non-null values? <span id="more-7"></span>(eg. you have to store social security numbers but you have people working in other countries with no SSN) The ANSI standards says that the non-null values should be unique, however, the MSSQL requires all value to be unique, that is, you can have only one null in a unique column. The first approach says that NULL can&#8217;t be equal to NULL by definition, so I can handle any number of NULL values. The second approach says that you can&#8217;t insert a value into the column which is already there, and I can find a NULL among the values&#8230; Whatever, the point is that it can be quite bothering, or to be precise, it could have been bothering as in SQL2008 you have an almost nice workaround for it. The filtered index is a special kind of index which contains the keys for only a subset of the table, filtered by a WHERE clause. So you can create a filtered index this way:</p>
<pre class="brush: cpp;">CREATE INDEX ix_filtered ON dbo.MyTable (col1) where col2 &gt; 55
</pre>
<p>Or if you want to use it to remediate your unique index with multiple NULL values problem, it will look like this:</p>
<pre class="brush: sql;">CREATE INDEX ix_filtered ON dbo.MyTable (col1) where col1 is not null
</pre>
<p>A short demo:</p>
<pre class="brush: sql;">
CREATE TABLE tempdb.dbo.t1 (col1 int)
CREATE UNIQUE INDEX IX_t1_col1 on tempdb.dbo.t1 (col1)
WHERE col1 IS NOT NULL
-- insert a few rows...
INSERT INTO tempdb.dbo.t1 VALUES (1),(2),(NULL)
--this will fail...
INSERT INTO tempdb.dbo.t1 VALUES (1)
-- but this won't...
INSERT INTO tempdb.dbo.t1 VALUES (NULL)
</pre>
<p>Here you go. It&#8217;s quite quick-and-not-so-dirty. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.rollback.hu/2008/04/unique-index-vs-multiple-null/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

