2016. február 16., kedd

Hiányzó indexek lekérdezése MS SQL-ben

Az MS SQL Server 2005+ nyomon követi, hogy szerinte milyen indexek hiányoznak, amiket ki is lehet nyerni belőle. Az alábbi SQL utasítás különböző statisztikai adatokat listáz valamint le is generálja a szükséges CREATE scripteket.

SELECT
migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) AS improvement_measure,
mid.database_id,
DB_NAME(mid.database_id) AS database_name,
mid.[object_id],
'CREATE INDEX [missing_index_' 
+ CONVERT (varchar, mig.index_group_handle) + '_' 
+ CONVERT (varchar, mid.index_handle) + '_' 
+ LEFT (PARSENAME(mid.statement, 1), 32) + ']' 
+ ' ON ' + mid.statement 
+ ' (' + ISNULL (mid.equality_columns,'') 
+ CASE WHEN mid.equality_columns IS NOT NULL AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END + ISNULL (mid.inequality_columns, '') + ')' + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') AS create_index_statement,
migs.*
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * (migs.avg_user_impact / 100.0) * (migs.user_seeks + migs.user_scans) > 10

ORDER BY migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC

Vannak hiányosságai is ennek a funkciónak:




  • nem veszi figyelembe az index létrehozási költségét
  • sosem ajánl partícionálást megoldásként
  • nem mond semmit az ideális sorrendről a több mezőt magába foglaló indexnél
Bővebb leírás és elemzés itt található.

2016. február 15., hétfő

Lapozás SQL-ben

Többféle modell létezik a lapozott adatok megjelenítéséhez:

  1. Egyszerű lekérdezése lapozás nélkül, majd pedig a megjelenítő alkalmazás feladat megoldani, hogy lapozhatóan legyen a megjelenítés
  2. Lapozott lekérdezés a ROW_NUMBER használatával
  3. Lapozott lekérdezés az OFFSET és FETCH NEXT használatával 
Mindkét esetben, amikor már eleve lapozva olvastatjuk fel az adatokat, érezhető a javulás. Célszerű az OFFSET és FETCH NEXT módszert alkalmazni nagy adatmennyiségnél az SQL SERVER 2012+ verziókban. Bővebb leírás és sebességteszt itt található.




Példakódok a lapozáshoz:  

"ROW_NUMBER" használata:

DECLARE @PageNumber AS INT, @RowspPage AS INTSET @PageNumber = 2SET @RowspPage = 10 

SELECT * FROM (             SELECT ROW_NUMBER() OVER(ORDER BY ID_EXAMPLE) AS Numero,                    ID_EXAMPLE, NM_EXAMPLE , DT_CREATE FROM TB_EXAMPLE               ) AS TBLWHERE Numero BETWEEN ((@PageNumber - 1) * @RowspPage + 1) AND (@PageNumber * @RowspPage)ORDER BY ID_EXAMPLE
GO


"OFFSET" és "FETCH NEXT" használata (SQL SERVER 2012):

DECLARE @PageNumber AS INT, @RowspPage AS INTSET @PageNumber = 2SET @RowspPage = 10

SELECT ID_EXAMPLE, NM_EXAMPLE, DT_CREATEFROM TB_EXAMPLEORDER BY ID_EXAMPLEOFFSET ((@PageNumber - 1) * @RowspPage) ROWSFETCH NEXT @RowspPage ROWS ONLY
GO

10 tipp C# fejlesztőknek

Néhány hasznos tanács példakóddal illusztrálva:
http://www.developer.com/net/top-10-tips-for-c-programmers.html

2016. február 3., szerda

SSRS local cache és a Visual Studio

Az SSRS riportok fejlesztése során meglehetősen idegesítő funkció, hogy az előnézetben megjelenített adatok cache-elve vannak ahelyett, hogy frissen felolvasná a rendszer minden egyes lekérdezésnél. Az explicit frissítés sem mindig tölti újra az adatokat.

A legjobb módszer, ha töröljük a riporthoz tartozó .data fájlt, ami a [riport-neve].rdl mellett található. Szerencsére van automatizálható módszer is az állandó kézi törlés helyett.

Visual Studio-ban a Tools > External Tools menüpontot használva meg lehet hívni külső alkalmazásokat is megfelelően felparaméterezve. Ezen a felületen be lehet állítani, hogy gombnyomásra megerősítés kérése nélkül töröljön minden cache fájlt a Solution minden almappáján belül. Célszerű bepipálni a "Use Output window"-t, mivel így azt fogja használni kimenetnek a CMD shell, azaz például a törölt fájlok listája is, illetve az esetleges hibaüzenetek is láthatók lesznek.




Ezt követően, amikor a későbbiekben szeretnénk üríteni a cache-t, akkor a Tools > Clear Report Data Cache menüpontot kell kiválasztani.


2016. január 31., vasárnap

Lean Poker workshop

Hétvégén részt vettem egy Lean Poker nevű eseményen, ami egy szakmai workshop volt az Emarsys CraftLab szervezésében. A Lean Poker alapvetően a lean startupból nőtte ki magát és mint olyan, itt is az számít, hogy ki mennyire képes felmérni a piaci helyzetet és reagálni a körülmények változására. Ebből adódóan a workshop célja,  hogy fejlessze ezen képességeinket. Az eseményről bővebb infó itt található.

A feladat 

Néhány fős csapatokba szerveződve készítettünk csapatonként egy-egy poker robotot, amik folyamatos házibajnokság keretében mérték össze tudásukat egymással szemben. A workshop felépítése kb. 1 órás fejlesztői rész, rövid össznépi élménybeszámoló és szünet hármasok egymásutánjából állt, egy beszélgetős ebédszünettel kibővítve. A beszámolók során minden csapat elmondhatta, hogy mivel küzdött és milyen játékstratégiával próbálkozott. Mivel nem volt tétje a "versenynek", így minden csapat nyugodtan megoszthatta tapasztalatait.

Continuous Integration and Deployment

A workshop során a Continuous Integration and Deploymentbe kóstolhattunk bele, aminek az a lényege, hogy minden változtatás azonnal ki is megy éles környezetbe, feltéve, hogy fordul a kód. Alapvetően tetszik az elgondolás, hogy ezzel elvileg csak kis változtatások történnek, ráadásul maximum néhány órás nagyságrendeken belül meg is van a visszajelzés, hogy bevált-e a módosítás. Valamint elvileg ezzel együtt jár az is, hogy a fejlesztők ennek tudatában mindig csak átgondolt és jól működő változtatásokat csinálnak.

Véleményem szerint egy nagyon hasznos dolog a Continuous Integration System, vagyis egy olyan rendszer, ami minden változtatás esetén rávizsgál, hogy legalább fordul-e a kód. Viszont nem teljesen értek egyet a Continuous Deployment gyakorlati használhatóságával. Számos helyen, például egy 24 órában működő diszpécseri szolgálatnál, ahol jelentős az automatizált működés, egy hibás változtatás sokáig rejtve maradhat, komoly anyagi károkat okozva.


Összefoglalás

Az esemény egyaránt érdekes volt számomra mind emberi, mind szakmai szemszögből nézve. Szeretek gondolkodós feladatokat megoldani, rendszereket tervezni, amit itt aktívan kiélhettem. Megfelelő arányban vették komolyan és lazán a csapattársaim az egész "versenyt", olyan volt a légkör, mintha csak néhány barát ült volna össze egy könnyed kódolásra iszogatás közben. 

A csapatunkban éppúgy volt rutinos programozó, mint IT-n kívülről érkezett is. A kezdeti káoszt tovább erősítette az a tény is, hogy szinte mindenki ismeretlenül került össze. Idővel leküzdöttük a káoszt, ami nagyban elősegítette a hatékony munkaszervezést. Ezt követően érezhetően jobban tudtunk együttműködni, ami meglátszott az eredményünkön is: már "csak" stagnált az arányunk a relatív eredménytáblában :)

Összességében jelentős tanulság volt számomra, hogy mennyire fontos az emberi kapcsolat a csapaton belül. Nem elhanyagolhatók egy projekt kapcsán az egyének szakmai kompetenciái, de ennél is fontosabb, hogy tisztában legyünk azzal, kivel milyen formában lehet és kell kommunikálni. Tudni kell, ki mennyire és milyen jellegű feladattal terhelhető, hogy hatékonyan lehessen megosztani a munkát. Igenis kell erre időt szánni a munka elején, főként, ha ismeretlenek a társak tapasztalatai. Másrészről ismét előjött, hogy mennyire lényeges, hogy szánjunk időt a tesztekre, kifejezetten dinamikus nyelvek esetében.


A szervezéssel teljesen meg voltam elégedve, mivel korrekten fel volt építve, hogy mi a menetrend aznapra és szakszerűen le is vezették a terveknek megfelelően. Tetszik a kezdeményezés, mivel azon túlmenően, hogy jó móka, tanít is.

2016. január 14., csütörtök

Windows timeserver hangolása

Windows rendszeróra automatikus szinkronizálásakor alapértelmezetten a time.windows.com időkiszolgáló van beállítva 7 napos frissítési periódussal. A szinkronizáláshoz az UDP 123 port nem lehet letiltva, mivel ezen keresztül kommunikál.

Time server beállítása

Ahhoz, hogy működhessen a szinkronizálás, előbb be kell állítani egy központi rendszert, egy time szervert, amitől kéri el a pontos időt. Ezt a Dátum és idő beállításoknál lehet megadni:


Célszerű lecserélni az alapértelmezett time.windows.com kiszolgálót, mert megbízhatatlan, ahogy már régebben is írták róla, például itt vagy itt, hogy nem ajánlják a használatát. Ezt a napokban magam is tapasztaltam Windows Server 2012-n, így meg tudom erősíteni, hogy ma is az, ezért helyette a time.nist.gov-ot használom, eddig problémamentesen.


Frissítési periódus módosítása

Miután sikeresen be lett állítva, hogy milyen időkiszolgálót használjon, ajánlott a frissítés gyakoriságát is megemelni, mert a heti egyszeri szinkronizálás az majdnem annyit ér, mintha emberöltőnként lenne, ennyi idő alatt komoly eltérés keletkezhet több rendszer ideje között.

Szerencsére van több mód is arra, hogy megváltoztathassuk a periódust. Egyik lehetőség, amit a Microsoft ír, hogy egy registry kulcsot módosítunk a kívánt másodpercekkel. Egy másik, ami szerintem szebb, hogy beütemezünk egy feladatot a kívánt gyakorisággal.


  • Registry módosítása
Az alábbi kulcsot kell módosítani a registry-ben: 
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\
services\W32Time\TimeProviders\NtpClient

Ezen belül a SpecialPollInterval tartalmazza másodpercben mérve, hogy mennyi idő elteltével kell újra frissíteni a rendszerórát.

  • Ütemezett feladat
Az előbbinél szerintem sokkal szebb megoldás, hogy ha készítünk egy bat fájlt, amit az Ütemezőnek odaadunk, hogy a kívánt időközönként futtassa meg. A beütemezett fájl tartalma az alábbi legyen:

net start w32time
w32tm /resync

Működését tekintve elindítja a Windows Time szolgáltatást, ha esetleg még nem futna, majd utána kiadja a szinkronizálás parancsot. Ütemezett feladat létrehozásáról bővebben itt lehet olvasni. Ezen módszer mellett eléggé meggyőző érv, hogy az Ütemezőnek köszönhetően egy barátságos grafikus felületen keresztül lehet megadni a gyakoriságot, szemben a registry-vel, amiben eleve nem szívesen módosít az ember.

2016. január 13., szerda

Beragadt Windows RDP session

A napokban megesett velem, hogy egy Windows Server 2012-es gépre próbáltam bejelentkezni távoli asztallal (RDP) és a megnyíló ablakban folyamatosan azt jelezte, hogy épp próbál kijelentkezni. Néhány perces várakozás utána megszakítottam a kapcsolatot, majd pár órával később ismét megpróbáltam, ekkor vált már elkerülhetetlenné. Továbbra is a kijelentkezés képernyő fogadott.

Az MSDN-en rátaláltam két hasznos alkalmazásra. Az egyik a Qwinsta, ami az RDP sessionökról, munkamenetekről mond információt, a másik pedig a Rwinsta, aminek a segítségével törölni lehet adott RDP sessionöket.

Ezek segítségével sikerült megfelelően kijelentkeztetnem a beragadt felhasználómat és megszakítanom a munkamenetet.

Első lépésként egy másik felhasználó nevében, egész pontosan Adminisztrátorként sikeresen beléptem a távoli gépre, és qwinsta paranccsal kilistáztam a munkameneteket. Ezt követően a rwinsta "sessionname" utasítással lezártam a megfelelőt. Ezután már gond nélkül be tudtam jelentkezni ismét.


Azóta rátaláltam egy másfajta megközelítésre, ami szintén megoldás lehetett volna a problémámra: a távoli asztal a /console vagy /admin kapcsolóval történő indítása. A választás attól függ, hogy Windows Server 2008, vagy annál újabb rendszerről van-e szó, mivel a WS 2008-as idejében történt változás.  Ez a változtatás azt hozta magával, hogy lényegében a /console érvénytelenítve lett, nincs már rá szükség. A kapcsolókról és magáról a változtatásról itt lehet olvasni. 

A problémámhoz kapcsolódóan az volt a lényeges, hogy ezzel a módszerrel mindig be lehet kapcsolódni a session0 munkamenethez, vagyis olyan, vagy legalábbis nagyon hasonló hozzáférést ad a szerveren a konzolhoz, mintha nem is RDP-n keresztül léptem volna be, hanem fizikailag ténylegesen az adott gépről futtatnám. A módszer hátránya, hogy megszakítja annak a munkamenetét, aki szintén ilyen módon volt becsatlakozva.