Category Archives: Szakmai élet

SQL Server memória hiány miatti lassú lekérdezés

Érdekes hibába futottam bele mostanában. A lapotopomban csak 8G RAM van, így az azon futó SQL servernek nem sok marad, amikor a Chrome, a Visual Studio 2015 és más memóriazabáló alkalmazások elkezdenek terjeszkedni.
A probléma az volt, hogy egy olyan lekérdezés, amely Sortot tartalmazott a szokásos 2-3 mp helyett fél-egy percig futott. A végrehajtási tervben volt egy figyelmeztetés, hogy a sort operátor kénytelen kipakolni a rendezést a tempdb-be (spill). De ettől még nem kellett volna ilyen lassúnak lennie. Csak 3500 sorról volt szó, ez azért belefért volna memóriába.

A select * from sys.dm_exec_query_memory_grants lekérdezésből kiderült, hogy a lekérdezés sortjának kellett volna 10M memória, de nem tudott annyit kapni, ezért várakozott, és aztán 20 másodperc múlva egyszer csak timeout lett, és kényszeredetten csak nekifogott végrehajtani a sortot a tempdbben.

Azaz egy egy nem szokványos lassú lekérdezés volt, nem sok lapolvasással járt, mint a tipikus rosszul optimalizált lekérdezések, hanem a memory grantre várt.
A megoldás az lett, hogy beállítottam 1G min memory-t az SQL Servernek, így már kiszámíthatóan jól érzi magát.

Egy rendes szerveren valószínűleg ritkább az ilyen memória kényszer, de azért jó tudni róla.

Egy példa mitől fordul le állandóan egy .NET project

Bosszantó, amikor semmit nem változtatsz, mégis újrafordul pár project egy nagyobb solutionben. Ha bekapcsolod a diagnostic build loglevelt, akkor egyből kiderül az ok. Pl. most nálam:

Project ‘Basics’ is not up to date. Project item ‘C:\ATS\Basics\x64\lz4X64.dll’ has ‘Copy to Output Directory’ attribute set to ‘Copy always’.

Update: egyéb okok: felesleges referenciák illetve Resource-ként megjelölt file, ami nem is resource, csak sima xml, ki kell másolni a kimenetbe.

.NET fejtörő

Élő kódból. Az első megoldás jól működik, a második nem, mi lehet az oka? A hibajelenség, hogy az első beállítja a TickerId-t az objektumon belül, a második nem.

Parallel.For(0, tickOhlcs.Count, i => tickOhlcs[i].SetTickerId(key.TickerId));

Parallel.ForEach(tickOhlcs, tickOhlc => tickOhlc.SetTickerId(key.TickerId));

2 karakter, és máris más az execution plan

Az eredeti lekérdezésben az ORDER BY így nézett ki: order by BDT.
Ez a számított oszlopra vonatkozott, azért a szervernek meg kellett oldania a rendezést egy külön lépésben. A b.BDT után viszont már tudja használni az alatta levő index rendezettségét, így nem kell rendeznie. 4x teljesítménynövekedést okozott ez a 2 karakter.

select
dateadd(second, @dtModifier, BDT) BDT,
cast(O as real) O, 
cast(H as real) H, 
cast(L as real) L,
cast(C as real) C,
V
from dbo.Bar b with (nolock)
where b.TickerID = @TickerID
and b.BDT >= @StartDate
and I = @I
order by b.BDT

Intra query deadlock

Ma láttam egy újfajta deadlockot, amiben az SQL Server által párhuzamosan végrehajtott lekérdezés szálai akadtak össze. Azaz ugyanaz a PID akadt össze magával.

Először arra gondoltam, lefogom 1 szálra a lekérdezést maxdoppal, de szerencsére nem volt jól optimalizálva, így jól fel lehetett gyorsítani. 240000 lapolvasásról 4-re. :) Így már magától soros lett a plan, volt deadlock, nincs deadlock.

Bob is írt már erről.

Exam 70-459: https://www.microsoft.com/learning/en-in/exam-70-459.aspx done

Na, ez is megvan. :)

Ez is upgrade, két vizsgát tartalmazott, és ebben már volt 2014-es tartalom. Két témakört érintettek, az egyik az In-Memory DB (mi más?), a másik a delayed durability. Ja, és a clustered columnstore index is előjött egy kérdésben.

Szokás szerint volt pár nem jól definiált kérdés, ezeknél már kommenteztem, mert utálom, hogy ennyire nem nézetik át a kérdéseket.

Az in-memory-snál elég sokat elidőztem, mivel belementek, hogy milyen izolációs szintek vannak benne, és melyik alkalmas az adott feladatra, amit a scenarióban leírtak. A scenariók itt is km hosszúak, kicsit be is tojtam az elején, hogy nem lesz elég időm. De kiderült, hogy sok nem scenarió alapú kérdés is volt, azokat gyorsan meg lehet válaszolni.

Csak az inmemory-s rész a maga kb. 5 kérdésével elvitt vagy 20 percet, de a többi már emészthetőbb volt.

Idén már csak két tervem van, az MVC vizsga és a BI-os SQL rész. Az MVC-t valszeg letolom jövő héten még, amíg tart a second shot, ki tudja, hátha egyszer megbukom, nyugalmat ad, hogy nem dobok ki 75EUR-t az ablakon.

Szeméttel teli plan cache

Ha a plan cache tele van csak egyszer használt planekkel, akkor azok csak feleslegesen eszik a memóriát.
Az alábbi lekérdezés erre világít rá:

SELECT objtype AS [CacheType]
        , count_big(*) AS [Total Plans]
        , sum(cast(size_in_bytes as decimal(18,2)))/1024/1024 AS [Total MBs]
        , avg(cast(usecounts as bigint)) AS [Avg Use Count]
        , sum(cast((CASE WHEN usecounts = 1 THEN size_in_bytes ELSE 0 END) as decimal(18,2)))/1024/1024 AS [Total MBs – USE Count 1]
        , sum(CASE WHEN usecounts = 1 THEN 1 ELSE 0 END) AS [Total Plans – USE Count 1]
FROM sys.dm_exec_cached_plans
GROUP BY objtype
ORDER BY [Total MBs – USE Count 1] DESC

Megkérnélek benneteket, akik éles, nagy terheltségű SQL szervert üzemeltetnek, hogy futtassátok le a fenti parancsot, és küldjétek el az eredményt, kíváncsi vagyok, hol-milyen eredmények jönnek vissza.

Exam 70-457 Transition Your MCTS on SQL Server 2008 to MCSA: SQL Server 2012 done :)

Ma volt egy szabad napom, gyorsan lenyomtam ezt is.

A vizsga a szokásos volt, 0,8-e normál, rendes kérdések, 20% nehezen megragadható marhaság. 50 kérdés volt, ezzel le van tudva a 70-461 és a 70-462. 700 ponttól lehet átmenni, nekem 833 volt a 461-es rész, 900 a 462-es. Látszik, hogy developer agyam van. :)

Ha jól emlékszem nem volt benne egyetlen 2014-es kérdés sem, ez számomra szomorú. Valójában én a 2014 vizsgákat akartam letenni, de nincsenek most ilyenek. Gondolom majd a 2016-osnál lesznek új vizsgák, nem akarják lejáratni két évente a certeket.

Ami érdekes volt, eléggé rámentek a Windowing Functionökre, erre érdemes mindenkinek gyúrni (egyébként is hasznosak). De csak a 2005-ös szinten kérdezték, nem mentek bele a 2012-es újdonságokba (framing), pedig itt vannak az igazi csemegék.

A következő lukas napon jön a 459, abban már tényleg várhatóak 2014-es kérdések, majd megírom, mire kíváncsiak.

Task.Run Etiquette Examples: Don’t Use Task.Run in the Implementation

Az async – await dolgokkal fel lehet szabadítani pl. as ASP.NET által is használt ThreadPool szálakat, hogy míg egy hosszú ideig tartó nem CPU hanem IO intenzív folyamat fut, addig legyen szabad szál kiszolgálni a rendes, kicsi, gyors kéréseket.

De ha úgy aszinkronítunk egy blokkoló, IO intenzív kérést, hogy becsomagoljuk Task.Run-ba, akkor adtunk a sznak egy pofont, mert pont ugyanabból a ThreadPoolból vettünk el szálat, mint amit az ASP.NET is használ (feltételezve az alap TaskSchedulert használjuk). Ráadásul még context switch is lesz a szálak között, stb.

Az igazi aszinkron cuccosok (pl. .NET szerviz hívó osztályok és adatbázis kezelő osztályok) IO completion portot használnak, amivel sok blokkoló folyamatot tudnak monitorozni kevés szálon, nem minden egyes folyamathoz egy szálat használva, mint a Task.Run-os megoldás.

Bővebben a témáról itt.

Új tanfolyam ötlet – Winternals

Két új tanfolyamon töröm a fejem, kíváncsi vagyok, volna-e rá érdeklődés?

Az egyik egy Windows Internals jellegű tanfolyam. Annak idején le is vizsgáztam a témából, ideje lenne mindenkinek átadni a téma érdekes és hasznos részeit. A témák adottak, Russinovich-ék könyve az alap, ezt egészíteném ki developer specifikus dolgokkal, mint WinDB, SOS, mi látszik az egészből .NET-ből programozva, GC és Win mem kapcsolata, a sysinternalsos toolok mire valók, stb. Még nincs kialakult kép a fejemben a pontos tematikáról, ez még csak puhatolózás. Szóval, érdekelne valakit? Esetleg témajavaslat, mi az, ami miatt befizetnél egy ilyen tanfolyamra?

A másikról majd egy külön bejegyzésben írok.