Archive for the ‘SQL Server’ Category

Érdekes SQL programozási hibák

Wednesday, April 27th, 2011

Előző héten két érdekes hibát láttam ügyfeleknél.
Az egyikben láttam, hogy a lekérdezés végrehajtási tervében konverzió van, datetime -> integer, emiatt scan volt seek helyett, azaz lassú volt a lekérdezés.
Ami fura volt ebben, hogy egy izeID oszlop volt összehasonlítva egy datetime értékkel. Az ID-k tipikusan intek, megnézve a táblát tényleg az volt. Volt egy lokális változó, ami copy-paszta miatt datetimera sikerült int helyett, és ezzel írták tovább a where szűrést. A lekérdezés már 2 éve ment élesben. :)
Ami érdekes volt benne, hogy funkcionálisan jól működött, a számok szépen konvertálódtak dátumokká és vissza, nem volt vele gond, csak lassú volt az egész. Bizarr hiba.

A másik esetben egy ilyen lekérdezés volt:


declare @a int
while valami
begin
  select @a = oszlop from tabla where ...
end

Furcsa volt, hogy a @a furcsa módon tartalmazott értéket akkor is, amikor nem érintett sort a select a where miatt.
Jobban belegondolva ez nem is fura, hisz a select NEM ad értéket a változónak, ha nem érint sort, és NEM is nullázza ki. Első iterációkor a @a null, hisz nem kapott értéket, a második iterációnál meg benne volt az első futás eredménye, ami már nem null volt, bár azt várták. Nem nagy hiba, de időrabló tud lenni.

option(recompile) nem mindig működik

Thursday, April 14th, 2011

Hirtelen egymás utáni napokon 3 cégnél égetett be az SQL Server 2005-től létező option(recompile), miután nem működik.

A hint célja az lenne, hogy a konkrét paraméterértékek ismeretében kérünk egy újrafordítást, így az optimizer ki tud dobni felesleges ágakat a lekérdezésből, ezzel nagyon hatékony terveket tud létrehozni egyes speciálisabb lekérdezésekhez.
Pl. gyakori, hogy a paraméterre csak akkor kell szűrni, ha nem null, ha null, jöjjön vissza minden sor:

… where @param is null or oszlop = @param

Ez alapban scan lenne, lassú. Az option(recompile) hatására azonban ha a @param null, akkor teljesen kiesik a sor, ha nem null, akkor meg leegyszerűsödik erre:

… where oszlop = @param

Ez meg már jó kis gyors seek lesz, megfelelő index esetén.

Mi itt a gond? Csak az, hogy ez sok verzión NEM működik. Pedig működött. :)

Az ok a következő. SQL 2005-ben még nem működött. 2008-ra megcsinálták, ment, csakhogy egy igen durva bugot is beleszereltek: ha többen hajtanak végre ilyen hintelt lekérdezést, akkor összekeveredhetnek az eredményhalmazok. Ez az innye, bazmeg típusú bug. Gyorsan ki ki kommenteltek pár sort, mivel megvarrni meg nem olyan egyszerű, mint elrontani. Így ez most nem megy az újabb SQL Servereken.
Erland barátunk szerint az R2 RTM NEM tartalmazza még a javított verziót (magyarul helyesen működik, nem nem gyorsít).
Viszont ez az R2 CU1 már javítja.
Ezen doksi szerint már 2008-hoz is van javítás, a CU5-ben.

Már csak le kéne cseréni a cégeknek a 2005-öt. :)

Adding External References to SQL CLR Projects

Friday, February 25th, 2011

Ha egy SQLCLR eljárásból kell meghívni valamilyen külső komponenst.
A trükk az, hogy a külső assembly-t is be kell telepíteni az SQL serverbe CREATE ASSEMBLY-vel, mivel az csak onnan hajlandó betölteni assemblyket (pár fw. alap dllt kivéve).

SQLXMLBulkload

Monday, February 7th, 2011

Már el is felejtettem, hogy van ilyen. Öregszem. :)

How to Share Data Between Stored Procedures

Thursday, January 6th, 2011

Felírom magamnak, hasznos lehet.
http://www.sommarskog.se/share_data.html

Defensive Database Programming ingyenes könyv

Saturday, May 15th, 2010

Érdekesnek ígérkezik, ingyenes, letölthető könyv.

Szótöredék keresés SQL Serveren - furcsának ható hiba

Thursday, May 13th, 2010

Az alábbi kérdezték tőlem pár perce:


SELECT [text]  FROM [table1] WHERE [text] like '%rekes%'

A rekesz szót nem találja meg, ha magyar a collation az oszlopon. Ez természetes, a kettős betűket ezzel a logikával kezeli a szerver, azaz egy betűnek tekinti őket. A where-be kell egy collation cast, mondjuk latin1-re, amiben nincsenek kettős betűk. Mondjuk ezután nem fog indexet használni a szerver, de a kezdő % miatt eleve nem használva.
Az alábbi példában az egyikkel collationnel megtalálja, másikkal nem.


SELECT [text]  FROM [table1] WHERE [text] like '%rekes%'
--  collate Hungarian_CI_AS
collate Latin1_General_CI_AS

Lehet csinálni indexelt, számított oszlopot is más collationnel, és arra szűrni, az gyorsabb lesz.

Random orderby Linq és EF használatával

Monday, October 12th, 2009

Az SQL Serveren szokásos orderby newid() szerveroldali megoldást csak linq to SQL esetén tudjuk kihasználni, szerveroldali függvénnyel. Az EF-ben az ilyesmi nem megy:


... orderby Guid.NewID() ...

Ez az EF verzió még nem tudja lefordítani szerveroldali kifejezéssé az orderby kifejezését.
Viszont a random rendezést át lehet nyomni kliensoldalra, ha a lekérdezést “materializáluk” (AsEnumerable) előbb:


Random rnd = new Random();
(from s in ATSEntities.Instance.Symbol
select s).AsEnumerable().OrderBy(o => rnd.Next()));

Nem guidot használtam, hanem Randomot, az kisebb költségű, és az én célomra nem baj, ha csak pszeudo-random a sorrend.

Deadlock bulk load során

Tuesday, August 4th, 2009

Párhuzamos bulk betöltések esetén deadlockolhatnak egymással a másoló szálak, főleg, ha vannak FK-ek a táblákon.

Sokféle megoldás adható a problémára.
1. Átmeneti táblába töltünk, amin nincsenek indexek és fk-k.
2. Lekezeljük a deadlockot, és ismétlünk.
3. tablock-kal töltünk be, ezzel azonban súlyosan visszavethetjük a párhuzamosságot.
Ezt ki lehet kényszeríteni központilag is:
EXEC sp_tableoption ‘Tick’, ‘table lock on bulk load’, ‘1′

Nekem ez jó volt, mert nálam az adatforrás volt lassú 1 szálon, ezért kellett 40, az SQL betöltések sorosítva is elég gyorsak, és nincs deadlock.

Histogramgenerálás SQL-ből

Monday, July 20th, 2009

SQL magazinból.
Fenn van az SQL Magazine 2000-2004 között itt az msdnen, jó cikkek vannak benne.

Scatter riportok a Reporting Servicesben

Wednesday, July 15th, 2009

A legtöbb riport item az RS-ben intuitív, na, ez nem az. Ezzel a chart fajtával nagyon jól lehet szemléltetni nagyszámú minta eloszlását, jól látszik pl. hol tömörödnek az értékek csoportokba (clusterekbe).

Nekem pl. intraday trade-ek elemzésére kiváló (példaként itt a rendszerem egyik riportja, a pötyösek a scatterek), mivel több mint ezer trade történik 2-3 évnyi adat tesztelése során, amelyek teljesítményét jól lehet vizualizálni a scatter chart segítségével valamely változó függvényében.

A chart beélesztésében ez segített.

Automatikus kurzor takarítás

Thursday, July 2nd, 2009

Na, ezt nem ismertem, pedig már 10 éve nyüvöm az SQL Servert.

Read-only filegroup, hogy ne lock-oljon az SQL Server? Nem.

Thursday, April 30th, 2009

Az egyik MCP vizsgán céloztak arra, hogy ha egy adatbázis valamely filegroupját read only-vá tesszük, akkor nem fog lockokat rárakni a szerver, hisz minek, úgyse lesznek módosító folyamatok.

Nos, ez elméletileg így lehetne, de nem így van. Ha az egész adatbázis read only, akkor viszont tényleg nem lockol, ami adhat némi teljesítmény nyereséget.

Másra azért jó:

Read-only filegroups, They provide you the following three benefits:

1. Can be compressed (using NTFS compression)
2. During recovery you don’t need to apply logs to recover a read-only file group
3. Protection of data from accidental modifications

A márciusi BI konferencia anyaga a weben

Monday, April 27th, 2009

Erről elfelejtettem írni, online minden anyag, így a screencastok is - az én részem a Reporting Services volt.

Az utóbbi időben sokat használom a Reporting Servicest a kereskedő algoritmusaim teszteredményeinek megjelenítésére, és egyre jobban szeretem.

Az Entity Frameworköt is gyúrom, na erről már vegyesebb véleményem van, de egyelőre még korai lenne világgá kürtölni, ha már jobban kiismertem, majd írok róla.

Előadásom az Architect Akadémián - SQL Server architect szemmel

Sunday, April 12th, 2009

Kicsit későn szólok, de ha valakit érdekel, még jelentkezhet, április 15-én lesz.
3×1 órában beszélek arról, hogyan lehet bevetni az SQL Serverek (2000-2008) okosságait egy új alkalmazásarchitektúra kidolgozása során. A cél nem annyira mélységi, mint szélességi bemutatása annak, mit lehet kihozni az SQL Serverből. Igyekszek olyan dolgokról is beszélni, amiről ritkán esik szó (pl. Query Notification, Service Broker), világnézet tágítás végett. Szeretném megmutatni, hogy az SQL Server nem egy egyszerű CRUD adatbázismotor, ahogy sajnos nagyon sokan használják.

Mikor építhetünk a sorok sorrendjére SQL Serverben?

Thursday, March 12th, 2009

Nappal DP tanfolyamot tartottam, éjszaka meg adatbázist optimalizálok egy ügyfelemnek, így most csak egy rövid, de érdekes cikket linkelek be.

.NET teljesítményhangolási tapasztalatok 6.

Monday, February 23rd, 2009

A Connection Poolról még pár gondolat. Jó, hogy van ez a pool, meg gyorsít is, örülünk neki, főleg webalkalmazásokban. Olyan appokban viszont, ahol állandóan futnak a dolgaink, mint egy asztali alkalmazás esetén, nem biztos, hogy érdemes mohón nyitni-zárni a kapcsolatot.
A tőzsdei kereskedési algoritmusaim backtestje során sok százezer paraméterkombinációt néz végig a gép, próbálja meghatározni a legvalószínűbb nyerési esélyűt vagy legnagyobb profit/szórással rendelkezőt (ennél jóval bonyolultabb a dolog, de ez most nem tőzsdés bejegyzés lesz).
A DAL-t úgy írtam meg ahogy webalkalmazásokban megszoktam, így minden egyes trade mentésénél nyitottam-zártam a connectiont. Profilerrel megnézve kiderült, hogy a pool ellenére is a futási idő harmada az open/close-zal ment el. Emiatt készítettem kétféle SqlHelper osztályt, az egyik állandóan nyitott kapcsolattal működik, a másik az egyéb helyekre nyit-zár mind eddig.
Összegezve, a connection pool kiváló dolog pillanatokra futó alkalmazásokhoz, mint a webalkalmazások, de nem érdemes erőltetni, ha több százezerszer kell nyitni-zárni a kapcsolatot.

.NET teljesítményhangolási tapasztalatok 5.

Thursday, February 12th, 2009

Szeretjük a connection poolt, de nem mindig.

Tudjuk, hogy manapság nem illik sokáig nyitva tartani az adatbázis kapcsolatot, hanem bemegyünk, kihozzuk a szükséges adatokat, majd lezárjuk a kapcsolatot. Régen (n > 10 év) ez nem volt okos dolog, mert lassú volt a belépés-kilépés. Ezért találták ki a Connection Poolt, amit OLEDB-ben még Session Poolnak hívtak. Egykutya.
Ez arról szól, hogy a kliens oldali adatelérő komponens, pl. az ADO.NET SqlClient providere (System.Data.SqlClient névtér és kölkei) újrahasznosítja a lezárt kapcsolatot. Azaz mi SqlConnection.Close-t mondunk, ő viszont a háttérben nem zárja le a kapcsolatot az adatbázis felé. Ha ezek után újra meg akarjuk nyitni egy kapcsolatot az adatbázis felé, nem hoz létre új kapcsolatot a provider, hanem visszaad egy használtat a poolból. Miért jó ez? Nyilván egy tényleges kapcsolat kiépítése igen költséges, TCP csatorna vagy Named Pipe session felépítése, autentikáció, ecetera. Ezt nagyon sokszor megússzuk, hála a poolnak. A pool 4-8 perc közötti véletlenszerű időközönként azért lezárogatja a használt kapcsolatokat, ott ne zápuljanak.
Nyilvánvaló, hogy felhasználónként egyedi poolok vannak, így egy sysadmin által eldobott kapcsolatot nem adja oda nekem, lópicinek a provider, ez csúnya luk lenne.
Lehet azért így is aljaskodni az új bérlőkkel. Mi van, ha becsatlakozok, kiadok egy use másik adatbázist, majd röhögve lezárom a kapcsolatot? És ha egy-ket set opciót átírok, pl. SET LANGUAGE urdi? Mit lát a következő hívó, aki megkapja a használt kapcsolatot? Hát amit beállítottunk az előző lépésben. Azért ez durván hangzik, ugye? Szerencsére a helyzet az, hogy alapban tiszta környezetet kapunk, köszönhetően annak, hogy a provider pool manager-e végrehajt egy sp_reset_connection hívást mielőtt visszaadná nekünk a használt kapcsolatot. Hogy ez pontosan mit csinál, azt egyszer már leírtam, tessék megnézni a listát.
Azaz bár nem kell minden egyes kéréshez új kapcsolatot megnyitni, azért egy sp hívás csak történik pluszban a háttérben. SQL Profilerben látszik, hogy ez nagyon gyors, de azért ez mégis csak egy hálózati körülfordulás.
És most jön a trükk. Ha teljesen biztosak vagyunk benne, hogy nem tolunk ki a következő hívóval aki megkapja a használt kapcsolatunkat, akkor kikapcsolhatjuk a takarítást. A connection stringbe ezt kell beírni:


Connection Reset=false;

Nézzük meg az alábbi kódot:


SqlConnection conn = new SqlConnection("data source=.;initial catalog=ATS;Integrated security=true;");
SqlCommand cmd = new SqlCommand("sp_who", conn);
cmd.CommandType = CommandType.StoredProcedure;

for (int i = 0; i < 3; i++)
{
    conn.Open();
    cmd.ExecuteNonQuery();
    conn.Close();
}

Az SQL Profilerben ez látszik:


EventClass	TextData	SPID
Audit Login	-- network protocol: LPC
RPC:Completed	exec sp_who 	52
Audit Logout		52
RPC:Completed	exec sp_reset_connection 	52
Audit Login	-- network protocol: LPC
RPC:Completed	exec sp_who 	52
Audit Logout		52
RPC:Completed	exec sp_reset_connection 	52
Audit Login	-- network protocol: LPC
RPC:Completed	exec sp_who 	52
Audit Logout		52

Hoppá, ez nem az, amit vártunk! Csak 1 logint az elején és 1 logoutot a végén, közben meg az sp_resetconnectiont és az sp_who-nkat. Nem működik a pooling?
De. Csibész a profiler.
“The Audit Login event class indicates that a user has successfully logged in to Microsoft SQL Server. Events in this class are fired by new connections or by connections that are reused from a connection pool.”

Ha bekapcsoljuk a profilerben az Event Subclasst, kicsit tisztul a kép:


EventClass	TextData	SPID	EventSubClass
Audit Login	-- network protocol: LPC		1 - Nonpooled
RPC:Completed	exec sp_who 	52
Audit Logout		52	2 - Pooled
RPC:Completed	exec sp_reset_connection 	52
Audit Login	-- network protocol: LPC		2 - Pooled
RPC:Completed	exec sp_who 	52
Audit Logout		52	2 - Pooled
RPC:Completed	exec sp_reset_connection 	52
Audit Login	-- network protocol: LPC		2 - Pooled
RPC:Completed	exec sp_who 	52
Audit Logout		52	1 - Nonpooled

Szóval van pooling, csak a profiler ravaszkodik. Már kivert a víz. Viszont valami ebben zavar. A pooling ugye a kliensen van. Honnan tudja a szerver egy új parancs beérkeztekor az egy új parancsnak számít a kliens részéről a még nyitott kapcsolaton, vagy csak a poolból visszakapott kapcsolaton hajtanak végre egy új parancsot?
Szerintem ő mesterségesen szintetizálja a poolos login-logoutokat, az sp_reset_connection-ök beérkeztekor veszi őket körbe login-logout párossal, a feeling kedvéért. De ez csak tipp.

Kapcsoljuk ki a connection resetet:


SqlConnection conn = new SqlConnection(
    "data source=.;initial catalog=ATS;Integrated security=true;connection reset=false;");

Mit látunk a profilerben? Semmi nem változott! .NET fw. 2.0 felett nem lehet kikapcsolni az sp_reset_connection-t! Ezért nincs már a legújabb doksiban benne ez a beállítás.

Foly. köv.

A szeptemberi SQL konferencia screencastjai elérhetőek

Tuesday, October 21st, 2008

Itt.

A screencast nem olyan pörgős és humoros mint az elő előadás volt, de nem szeretek a monitornak bohóckodni. 500 embernek már lehet. Előadás közben meglepően más helyen vagyok a tudatállapotok szivárványán, pedig nem is kokszolok. :)
Persze tartalmilag minden benne van, ami élőben ment. Jó tanulást hozzá!

Szaktanácsadó születik :-)

Tuesday, October 14th, 2008

Örömmel és nagy reményekkel közzéteszem, hogy 2009. január 1.-től független szaktanácsadóként folytatom a szakmai pályafutásom. Ennek megfelelően év végére átalakítom a website-om főlapját is, a megfelelő üzleti, kontakt, stb. információkkal kiegészítve.
A blogom változatlanul fog üzemelni, sőt, várhatóan több időm lesz rá, és jóval több témával is fogok foglalkozni (WCF, WWF, Windows Internals, DP újult erővel, stb.).

Ha .NET-alapú fejlesztéssel, tervezéssel vagy SQL Serverrel kapcsolatban tudok valakinek segíteni, januártól szabad vagyok. Az utóbbi két évben jó pár felkérést utasítottam vissza, jövőre erre már nem lesz szükség.

Részletek később, most igen sok intéznivalóm van…