{"id":460,"date":"2019-12-17T12:41:35","date_gmt":"2019-12-17T12:41:35","guid":{"rendered":"https:\/\/datarebus.wordpress.com\/?p=46"},"modified":"2021-04-09T08:14:29","modified_gmt":"2021-04-09T08:14:29","slug":"sql-server-memory-management-2","status":"publish","type":"post","link":"https:\/\/datarebus.com\/index.php\/2019\/12\/17\/sql-server-memory-management-2\/","title":{"rendered":"SQL Server Memory Management"},"content":{"rendered":"\n<p>T\u00fcm veritaban\u0131 sistemlerinde oldu\u011fu gibi SQL Server\u2019da da memory 2 farkl\u0131 ama\u00e7&nbsp; i\u00e7in kullan\u0131l\u0131r:<\/p>\n\n\n\n<ol type=\"1\"><li>Kendi i\u00e7 sistemleri (plan cache, baz\u0131 denetim DLL dosyalar\u0131 ve \u00e7al\u0131\u015fan kodlar, procedure cache vs) i\u00e7in ayr\u0131lan di\u011fer k\u0131sma g\u00f6re k\u00fc\u00e7\u00fck kalacak bir alan<\/li><li>Diskten okuma yazma i\u015flemlerini azaltmak ama\u00e7l\u0131 kullan\u0131lan ve SQL i\u00e7in ayr\u0131lan memory\u2019nin b\u00fcy\u00fck k\u0131sm\u0131n\u0131 olu\u015fturan \u201cBuffer Cache\u201d<\/li><\/ol>\n\n\n\n<p>Teknolojiye paralel olarak disk eri\u015fim h\u0131zlar\u0131 ne kadar artm\u0131\u015f olursa olsun disk eri\u015fimleri memory eri\u015fimlerine k\u0131yasla her zaman \u00e7ok ama \u00e7ok yava\u015f kalacakt\u0131r. Bunun nedeni de tabiki disk eri\u015fimlerinin mekanik aksamlardan sa\u011flan\u0131yor olmas\u0131d\u0131r. Yani bir disk kafas\u0131 fiziksel olarak ilgili alana y\u00f6nelmeli ve buradan okumay\u0131 ger\u00e7ekle\u015ftirmesi gerekir. Aksine memory okumalar\u0131 ise tamamen elektronik i\u00e7eriklidir. K\u0131saca bu pragraf\u0131n \u00f6zeti: diskler yava\u015f memory h\u0131zl\u0131d\u0131r.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img src=\"https:\/\/datarebus.files.wordpress.com\/2019\/12\/sql-server-logo.png?w=250\" alt=\"\" class=\"wp-image-117\" \/><\/figure>\n\n\n\n<p>Bu nedenle de veritaban\u0131 sistemleri okuyabildikleri kadar veriyi \u00f6nceden Cache \u00fczerine y\u00fcklerler. B\u00f6ylece SQL Server\u2019\u0131n ilk yapaca\u011f\u0131 i\u015flem talep edilen verinin Cache\u2019de olup olmad\u0131\u011f\u0131n\u0131 kontrol edilmesidir. E\u011fer var ise (cache Hit) disk eri\u015fimine gerek kalmaz.<\/p>\n\n\n\n<p>B\u00fcy\u00fck veriye sahip olan sistemlerde Cache, veritaban\u0131na k\u0131yasla ufak kalaca\u011f\u0131 i\u00e7in cache \u00fczerindeki veri ya\u015fland\u0131r\u0131l\u0131r ve belirli bir s\u00fcre burada kal\u0131p zaman\u0131n\u0131 dolduran k\u0131s\u0131mlar yeni okumalara yer a\u00e7mak ama\u00e7l\u0131 olarak diske yaz\u0131l\u0131r.<\/p>\n\n\n\n<p>\u015eimdi biraz scriptler ile SQL Server\u2019\u0131n kulland\u0131\u011f\u0131 memory konusunda bilgi alal\u0131m :<\/p>\n\n\n<p><!--StartFragment--><\/p>\n\n\n<blockquote class=\"wp-block-quote\"><p>SELECT<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; physical_memory_kb,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual_memory_kb,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; committed_kb,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; committed_target_kb<\/p><p>FROM sys.dm_os_sys_info;<\/p><\/blockquote>\n\n\n<p><!--EndFragment--><\/p>\n\n\n<p>Buradaki sonu\u00e7larn manas\u0131n\u0131 k\u0131saca a\u00e7\u0131klamak gerekir ise:<\/p>\n\n\n\n<ul><li><strong>Physical_memory_kb<\/strong>: sunucu \u00fczerindeki RAM miktar\u0131<\/li><li><strong>Virtual_memory_kb<\/strong>: sunucu \u00fczerindeki tan\u0131ml\u0131 sanal memory miktar\u0131<\/li><li><strong>Committed_kb<\/strong>: veritaban\u0131n\u0131n Buffer Cache i\u00e7in kulland\u0131\u011f\u0131 miktar<\/li><li><strong>Committed_target_memory_kb<\/strong>: Buffer Cache\u2019in kullanmak istedi\u011fi alan\u0131 g\u00f6sterir. Bu de\u011fer e\u011fer committed k\u0131sm\u0131ndan ufak ise verinin diske yaz\u0131lmas\u0131n\u0131n zaman\u0131 gelmi\u015f demektir. E\u011fer b\u00fcy\u00fck ise daha fazla memory kullan\u0131lmak \u00fczere talep edilecek manas\u0131na gelir.<\/li><\/ul>\n\n\n\n<p>Burada veritaban\u0131n\u0131z\u0131 performans olarak en iyi etkiyi sa\u011flayacak olan parameter, Buffer cache i\u00e7in ayr\u0131lan alan\u0131n yeterli olup olmad\u0131\u011f\u0131d\u0131r. Ek olarak a\u015fa\u011f\u0131daki sorgu ile de buffer cache i\u00e7in ne kadar alan ayr\u0131ld\u0131\u011f\u0131n\u0131 tam olarak tespit edebilirsiniz :<\/p>\n\n\n\n<div class=\"wp-container-1 wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<blockquote class=\"wp-block-quote\"><p>SELECT<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COUNT(*) AS buffer_cache_pages,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COUNT(*) * 8 \/ 1024 AS buffer_cache_used_MB<\/p><p>FROM sys.dm_os_buffer_descriptors;<\/p><\/blockquote>\n<\/div><\/div>\n\n\n\n<p>&nbsp;Peki bu alan\u0131 en \u00e7ok hangi tablo kullan\u0131yor :<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>SELECT<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; indexes.name AS index_name,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objects.name AS object_name,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objects.type_desc AS object_type_description,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COUNT(*) AS buffer_cache_pages,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COUNT(*) * 8 \/ 1024&nbsp; AS buffer_cache_used_MB<\/p><p>FROM sys.dm_os_buffer_descriptors<\/p><p>INNER JOIN sys.allocation_units<\/p><p>ON allocation_units.allocation_unit_id = dm_os_buffer_descriptors.allocation_unit_id<\/p><p>INNER JOIN sys.partitions<\/p><p>ON ((allocation_units.container_id = partitions.hobt_id AND type IN (1,3))<\/p><p>OR (allocation_units.container_id = partitions.partition_id AND type IN (2)))<\/p><p>INNER JOIN sys.objects<\/p><p>ON partitions.object_id = objects.object_id<\/p><p>INNER JOIN sys.indexes<\/p><p>ON objects.object_id = indexes.object_id<\/p><p>AND partitions.index_id = indexes.index_id<\/p><p>WHERE allocation_units.type IN (1,2,3)<\/p><p>AND objects.is_ms_shipped = 0<\/p><p>AND dm_os_buffer_descriptors.database_id = DB_ID()<\/p><p>GROUP BY indexes.name,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;objects.name,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;objects.type_desc<\/p><p>ORDER BY COUNT(*) DESC;<\/p><\/blockquote>\n\n\n\n<p>Peki, veri disk \u00fczerinden cache\u2019e okunuyor ve burada saklan\u0131yor. Belki daha \u00f6nce yazmay\u0131 unuttuk ama malum 8 KB olacak \u015fekilde formatlanm\u0131\u015f bir disk alan\u0131m\u0131z var. ayn\u0131 nedenle cache \u00fczerindeki minimum blok b\u00fcy\u00fckl\u00fc\u011f\u00fc de 8KB. Tabii bunun ne kadar\u0131n\u0131n ger\u00e7ekten dolu oldu\u011fu data b\u00fcy\u00fckl\u00fc\u011f\u00fcn\u00fcze ba\u011fl\u0131. Yani bir sat\u0131r\u0131 5KB b\u00fcy\u00fckl\u00fc\u011f\u00fcnde bir tablo tan\u0131mlam\u0131\u015f iseniz \u00e7ok kaba bir tarif ile her blokta 3KB bo\u015f alan\u0131n\u0131z var demektir.<\/p>\n\n\n\n<p>Peki cache \u00fczerindeki kay\u0131tlar\u0131n ne kadar ger\u00e7ekten dolu ve ne kadar\u0131 bo\u015f:<\/p>\n\n\n\n<div class=\"wp-container-2 wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<blockquote class=\"wp-block-quote\"><p>SELECT<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objects.name AS object_name,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objects.type_desc AS object_type_description,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; COUNT(*) AS buffer_cache_pages,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CAST(COUNT(*) * 8 AS DECIMAL) \/ 1024&nbsp; AS buffer_cache_total_MB,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CAST(SUM(CAST(dm_os_buffer_descriptors.free_space_in_bytes AS BIGINT)) AS DECIMAL) \/ 1024 \/ 1024 AS buffer_cache_free_space_in_MB,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CAST((CAST(SUM(CAST(dm_os_buffer_descriptors.free_space_in_bytes AS BIGINT)) AS DECIMAL) \/ 1024 \/ 1024) \/ (CAST(COUNT(*) * 8 AS DECIMAL) \/ 1024) * 100 AS DECIMAL(5,2)) AS buffer_cache_percent_free_space<\/p><p>FROM sys.dm_os_buffer_descriptors<\/p><p>INNER JOIN sys.allocation_units<\/p><p>ON allocation_units.allocation_unit_id = dm_os_buffer_descriptors.allocation_unit_id<\/p><p>INNER JOIN sys.partitions<\/p><p>ON ((allocation_units.container_id = partitions.hobt_id AND type IN (1,3))<\/p><p>OR (allocation_units.container_id = partitions.partition_id AND type IN (2)))<\/p><p>INNER JOIN sys.objects<\/p><p>ON partitions.object_id = objects.object_id<\/p><p>WHERE allocation_units.type IN (1,2,3)<\/p><p>AND objects.is_ms_shipped = 0<\/p><p>AND dm_os_buffer_descriptors.database_id = DB_ID()<\/p><p>GROUP BY objects.name,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objects.type_desc,<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objects.object_id<\/p><p>HAVING COUNT(*) &gt; 0<\/p><p>ORDER BY COUNT(*) DESC;<\/p><\/blockquote>\n<\/div><\/div>\n\n\n\n<p>Bu ne i\u015fimize yarar derseniz, asl\u0131nda \u00e7ok bir i\u015finize yaramaz ama en az\u0131ndan tablolar\u0131n\u0131zdaki bo\u015f alanlar\u0131, blob alanlar\u0131 ve fragmantasyonu d\u00fc\u015f\u00fcnmeye ba\u015flaman\u0131za yard\u0131mc\u0131 olur.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>DBCC DROPCLEANBUFFERS<\/p><\/blockquote>\n\n\n\n<p>Cache \u00fczerinde bir rahats\u0131zl\u0131k hissettiniz bu komutu \u00e7al\u0131\u015ft\u0131rabilirsiniz. SQL taraf\u0131ndan bakarsan\u0131z \u00e7ok istenen bir durum de\u011fil zira cache \u00fczerindeki t\u00fcm clean ya da dirty alanlar\u0131 diske yazarak cache\u2019I bo\u015faltacakt\u0131r. Dolay\u0131s\u0131 ile de ilk zamanlarda t\u00fcm okumalar disk \u00fczerinden yap\u0131laca\u011f\u0131 i\u00e7in bir s\u00fcre yava\u015flama olaiblir.<\/p>\n\n\n\n<h2>Page Life Expectancy<\/h2>\n\n\n\n<p>SQL Server i\u00e7in tan\u0131mlanan memory alan\u0131 ne kadar yeterli sorusuna en iyi cevab\u0131 verecek olan sorgudur. PLE \u00f6zetle, cache \u00fczerinde bir verinin ne kadar s\u00fcre kald\u0131\u011f\u0131n\u0131 g\u00f6sterir. E\u011fer bu s\u00fcre uzun ise sorun yok. Ama k\u0131sa ise bu datan\u0131n devaml\u0131 olarak cache \u00fczerinden diske aktar\u0131ld\u0131\u011f\u0131n\u0131 g\u00f6sterir. Bu da biraz daha memory ihtiyac\u0131na en iyi ipucudur. Di\u011fer taraftan b\u00fcy\u00fck veri \u00e7eken sorgular\u0131n \u00e7al\u0131\u015ft\u0131r\u0131l\u0131yor olmas\u0131 PLE de\u011ferini d\u00fc\u015f\u00fcr\u00fcr.<\/p>\n\n\n\n<p>SQL kitap\u00e7\u0131klar\u0131nda bu de\u011ferin &gt;300 olmas\u0131 talep edilir ama g\u00fcn\u00fcm\u00fczdeki RAM b\u00fcy\u00fckl\u00fcklerine bakar isek 300 bence biraz d\u00fc\u015f\u00fck.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>SELECT<\/p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *<\/p><p>FROM sys.dm_os_performance_counters<\/p><p>WHERE dm_os_performance_counters.object_name LIKE &#8216;%Buffer Manager%&#8217;<\/p><p>AND dm_os_performance_counters.counter_name = &#8216;Page life expectancy&#8217;;<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>T\u00fcm veritaban\u0131 sistemlerinde oldu\u011fu gibi SQL Server\u2019da da memory 2 farkl\u0131 ama\u00e7&nbsp; i\u00e7in kullan\u0131l\u0131r: Kendi i\u00e7 sistemleri (plan cache, baz\u0131 denetim DLL dosyalar\u0131 ve \u00e7al\u0131\u015fan kodlar, procedure cache vs) i\u00e7in ayr\u0131lan di\u011fer k\u0131sma g\u00f6re k\u00fc\u00e7\u00fck kalacak bir alan Diskten okuma yazma i\u015flemlerini azaltmak ama\u00e7l\u0131 kullan\u0131lan ve SQL i\u00e7in ayr\u0131lan memory\u2019nin b\u00fcy\u00fck k\u0131sm\u0131n\u0131 olu\u015fturan \u201cBuffer Cache\u201d [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[5,6,7],"_links":{"self":[{"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/posts\/460"}],"collection":[{"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/comments?post=460"}],"version-history":[{"count":1,"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/posts\/460\/revisions"}],"predecessor-version":[{"id":475,"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/posts\/460\/revisions\/475"}],"wp:attachment":[{"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/media?parent=460"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/categories?post=460"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/datarebus.com\/index.php\/wp-json\/wp\/v2\/tags?post=460"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}