Soci (Soczó Zsolt) szakmai blogja

2008.02.14.

Darkness falls

Filed under: Élet — Soczó Zsolt @ 22:45

http://index.hu/politika/belfold/dra0214/

“Az Országos Rendőr-főkapitányság közleménye szerint nincs szabályozás arra nézve, hogy mennyi ideig kell közzétenni a titkos nyomozások iratanyagát, így a hozzáférhetőség időtartamát az ésszerűség okán biztosították. A közlemény emlékeztetett arra, 3 iratanyag 2007. november 12-től december 29-ig volt elérhető, a többi anonimizált irat pedig 2007. december 29-e és 2008. február 1-je között. Így megvalósult az olajbizottság részére kitűzött feladat, a nyilvánosság tájékoztatása, olvasható a dokumentumban.”

Mindig elképedek ezen az országon, hogy ennyire hülyének lehet nézni az embereket. Hová süllyedünk még?
Persze a google cache-t nem lehet törölni. Főleg, ha annyira pöcsök, hogy a pdf meg kinn marad.

Milyen ironikus, hogy az előző pontomban ezt írtam:
“Mivel szabad informatikai adatok terén (meg más téren is) Magyarország a béka segge alatt van…”

A házi jósda szerint 2009-től már nem Magyarországon élek. Lehet, hogy nem is annyira eszement az ötlet? KZ, van valami jó új-zélandi állásod? :)

2008.02.13.

SQL Server 2008 újdonságok 20. – térbeli adattípusok 7.

Filed under: Adatbázisok,SQL Server,SQL Server 2008,Szakmai élet — Soczó Zsolt @ 01:00

Némi kihagyás után (dógozni is kell, meg a gyerekeknek gyógyulni) kicsit foglalkozzunk még a spatial adatokkal. Az eddigi részekben eljátszadoztunk velük, szép volt, csak arról nem volt szó, hogy működik ez az egész, ha sok adatban kell keresgélni? Alapban sok művelet piszok időigényes, mindenképpen szükség lenne valamilyen indexelési módszerre. De ezek az adatok messze nem olyan egyszerűen indexelhetők, mint mondjuk egy varchar.

A spatial index maga most is egy B* fa, csak a kihívás, hogyan lehet alakzatok adatait úgy átmasszírozni valami bináris adathalmazzá, ami aztán meggyosíthat bizonyos műveleteket, például távolságszámítást vagy metszet meghatározását.

Az index működését itt részletezik. A cikket olvasva meglehetősen bizarr dolog tárul a szemünk elé, amelyből jól látszik, hogy a spatial támogatás messze több, mint egy új CLR UDT.

Az első dolog, amit fogni kell, hogy a spatial indexek nem olyan egzaktak, mint amiket eddig láttunk. A részletek mellőzésével a következőről van szó.
A síkot felbontják cellákra, mint amikor “kockás” papírra rajzolunk. Az alakzatok ezekre a négyzetekre vannak fektetve. Minden cellát további cellákra bonthatjuk, és ott is meghatározhatjuk, mely al-cellákban van még benne egy alakzat, és melyben nincs. Ez a dekompozíciót max. 4 szinten folytatják, így egyre finomabb felbontásban gyűjtenek információt az alakzatról. Hogy ne szabaduljonak el az adatok, vannak szabályok, amelyek korlátozzák az adatmennyiségeket.

A sík feldarabolása az index létrehozásához

Érezhető, hogy be kell határolni a “kockás papír” méretét, hogy véges méretű legyen az index, erre az index létrehozásakor van lehetőség. Ez azonban csak a geometry típusra vonatkozik, a geographynál véges a területünk, hisz a Föld felszínéről van szó.

A geography típus ellipszoid adatinál még cifrább a helyzet, azokat levetítik síkba, és úgy dolgoznak vele.

Földi koordináták levetítése indexeléshez

A valóság persze sokkal összetettebb, de nem vagyunk térképészek, így legyen elég ennyi. :)

Mire jó ezek után egy spatial index? Megfelelő körülmények között az STIntersects(), STEquals(), és STDistance() metódusokat meg tudja támogatni egy spatial index.

Tegyünk vele egy próbát!

Az előző részben a Dunához közel eső városokat kerestük meg, nézzük meg ezt index támogatással!

A táblában a városok multi-pontként vannak felvéve, pedig mindegyik csak 1 pontból áll. Konvertáljuk át őket igazi ponttá, hogy minden művelet rendesen menjen rajtuk:

update City
set geom = geom.STStartPoint()

select
CITY_NAME, geom.ToString()
from City

Így az alapadataink:

Kosice                                             POINT (48.70000118311 21.2500004483)
Rijeka                                             POINT (45.333301183109988 14.433300448300003)
Lodz                                               POINT (51.778000183109988 19.4759994483)
Kalisz                                             POINT (51.757999183109995 18.083000448299998)
Sieradz                                            POINT (51.59600018311 18.732999448300006)
Piotrkow Trybunalski                               POINT (51.409000183109988 19.691000448300002)
Radom                                              POINT (51.39600018311 21.158000448299987)
Lublin                                             POINT (51.24200018311 22.577999448300005)
...

Vegyük elő korábbi példánkat, a Dunához 10 km-nél közelebbi városok listáját.

declare @danube geography = geography::STPointFromText('POINT(0 0)', 4326);

select @danube = @danube.STUnion(geom)
from River where NAME = N'Danube'

select CITY_NAME, 
geom.ToString() 'A város', 
geom.STDistance(@danube) 'Távolság a folyótól' 
from City
where geom.STDistance(@danube) < 10000
&#91;/source&#93;

A végrehajtási terv:

<a href='http://soci.hu/blog/wp-content/uploads/2008/02/spatialopwithoutindex.png' title='spatialopwithoutindex.png' target='_blank'><img src='http://soci.hu/blog/wp-content/uploads/2008/02/spatialopwithoutindex.png' alt='spatialopwithoutindex.png' /></a>

No, a Filternek kellene kiesni vagy legalábbis a költségének csökkeni az index hatására. Az alap beállításokkal hozzunk létre egy spatial indexet:


create spatial index idx_City_Spatial_1
on City(geom)

Elvileg ettől más lehetne a korábbi lekérdezés végrehajtási terve. De nem lesz az. Annyira kicsit a táblánk (pár 10 sor), hogy esze ágában sincs használni egy mozaikos, rácsos ide-oda vetített indexet, a sima Filter jobban megéri neki.

Nagyobb adatmennyiségre van szükségünk. Mivel szabad informatikai adatok terén (meg más téren is) Magyarország a béka segge alatt van, szedjünk össze némi adatot Amerikából. Itt letölthető sok izgalmas infó. Például a települések listája, koordinátái megérnek egy misét. Ez betöltöttem a USCity táblába, 35432 sor lett.

Keressük meg azokat a városokat, amelyek Los Angeles 10 km-es körzetében vannak:

declare @la geography = (select geom
from USCity
where name = 'Los Angeles' 
and County = 'Los Angeles County')

select name
from USCity
where geom.STDistance(@la) < 10000
&#91;/source&#93;

Nem kellene lokális változót bevezetni, de így szétválik a végrehajtási terv, így jobban látszik az index hatása.

A kimenet:
&#91;source='c'&#93;
Los Angeles
City Terrace
East Los Angeles
Vernon
Commerce
Huntington Park
Maywood
Florence
Bell
Walnut Park
&#91;/source&#93;

Index nélkül a végrehajtás átlagban 2800 ms-ot vesz igénybe, ebből kb. 2000 a CPU költség, azaz igen erősen processzor intenzív a szűrés. A lapolvasások száma 1850.

Rakjunk rá egy spatial indexet!

&#91;source='sql'&#93;
create spatial index idx_USCity_Spatial_1
on USCity(geom)
&#91;/source&#93;

A végrehajtási idő leesik 160ms-ra! A lapolvasások száma 1720 lett, azaz ebben nem lett jelentős különbség, de a CPU idő leesett kb. 50 ms-ra, 2000-ről. Azért ez igen nagy nyereség.

Az index nélküli végrehajtási terv:

<a href='http://soci.hu/blog/wp-content/uploads/2008/02/spatialopwithoutindex2.png' title='Spatial szűrés index nélkül' target='_blank'><img src='http://soci.hu/blog/wp-content/uploads/2008/02/spatialopwithoutindex2.png' alt='Spatial szűrés index nélkül' /></a>

Az előbbi index-szel:

<a href='http://soci.hu/blog/wp-content/uploads/2008/02/spatialopwithdefaultindex2.png' title='Spatial szűrés alap index-szel' target='_blank'><img src='http://soci.hu/blog/wp-content/uploads/2008/02/spatialopwithdefaultindex2.png' alt='Spatial szűrés alap index-szel' /></a>

A jobb alsó Clustered Index Seek érdekes. A Seek Predicate-je a következő:


Seek Keys[1]: Start: [AdventureWorks].[sys].[extended_index_80719340_64000].Cell_Id >= Scalar Operator([Expr1009]), 
End: [AdventureWorks].[sys].[extended_index_80719340_64000].Cell_Id <= Scalar Operator(&#91;Expr1010&#93;)
&#91;/source&#93;

Azaz, az XML Shredinghez hasonlóan itt is felépítenek egy segédtáblát az index részére, és abban keresnek. A segédtábla neve: &#91;sys&#93;.&#91;extended_index_80719340_64000&#93;.
Azonnal kísértést érzünk pesze, hogy belenézzünk:

&#91;source='sql'&#93;
select * from &#91;sys&#93;.&#91;extended_index_80719340_64000&#93;
&#91;/source&#93;

Meg is kapjuk a magunkét:

&#91;source='c'&#93;
Msg 208, Level 16, State 1, Line 1
Invalid object name 'sys.extended_index_80719340_64000'.
&#91;/source&#93;

Na ne hazudjunk kérem, menjünk csak be a DAC kapcsolaton kereszül (ADMIN:gépnév\instance név):

&#91;source='c'&#93;
Cell_Id      Cell_Attributes SRID        pk0
------------ --------------- ----------- -----------
0x200A2A2C04 1               4326        34751
0x200A2A3C04 1               4326        34756
0x200A2B3404 1               4326        34762
0x200A2B3704 1               4326        34763
0x200A2B3804 1               4326        34764
...
&#91;/source&#93;

Ebben az index táblában pont annyi sor van, mint az eredetiben, és a pk0 oszlop teremt kapcsolatot a kettő között, a végrehajtási tervben a bal oldali Merge Join illeszti a kettőt össze, imígyen: 

&#91;source='c'&#93;
(&#91;AdventureWorks&#93;.&#91;dbo&#93;.&#91;USCity&#93;.ID) = 
(&#91;AdventureWorks&#93;.&#91;sys&#93;.&#91;extended_index_80719340_64000&#93;.pk0)
&#91;/source&#93;

Az SRID oszlop ismerős lehet, az az adatunk SRID-je, volt már róla szó az <a href="http://soci.hu/blog/index.php/2008/01/21/sql-server-2008-ujdonsagok-14-terbeli-adattipusok-1/">első részben</a>. Az első két oszlop jelentése egyelőre ismeretlen.

Vessük össze amit a hátsó nyíláson át felfedeztünk a hivatalosan is látható infóval!


select name, spatial_index_type_desc, tessellation_scheme
from sys.spatial_indexes
where object_id = object_id('USCity')
name                                               spatial_index_type_desc                            tessellation_scheme
-------------------------------------------------- -------------------------------------------------- --------------------------------------------------
idx_USCity_Spatial_1                               GEOGRAPHY                                          GEOGRAPHY_GRID

Az index lehet GEOGRAPHY vagy GEOMETRY, nyilván az oszlop típusától függően. A tessellation_scheme a mozaikozás módszerét írja le, ez az a folyamat, amiben egyre kisebb cellákra osztják fel az indexelendő tartományt. A GEOGRAPHY_GRID az a piramisos, kifeketetős séma, ami látható volt a korábbi rajzon.
No, ezektől az adatoktól nem lettünk sokkal okosabbak.

Nézzük meg a másik rendszer-nézetet:

select * from sys.spatial_index_tessellations
where object_id = object_id('USCity')
object_id   index_id    tessellation_scheme            bounding_box_xmin      bounding_box_ymin      bounding_box_xmax      bounding_box_ymax      level_1_grid level_1_grid_desc              level_2_grid level_2_grid_desc              level_3_grid level_3_grid_desc              level_4_grid level_4_grid_desc              cells_per_object
----------- ----------- ------------------------------ ---------------------- ---------------------- ---------------------- ---------------------- ------------ ------------------------------ ------------ ------------------------------ ------------ ------------------------------ ------------ ------------------------------ ----------------
80719340    64000       GEOGRAPHY_GRID                 NULL                   NULL                   NULL                   NULL                   64           MEDIUM                         64           MEDIUM                         64           MEDIUM                         64           MEDIUM                         16

Ez már érdekesebb. A bounding_boxok nullok, mert mint írtam, nem kell határokat adni a geography indexnek, a Föld felülete véges határt alkot. A level_1_grid 64 és a level_1_grid_desc MEDIUM ugyanazt mondja, hogy 8×8-as a legdurvább felbontású rácsozat. Azért az elég nagy, az egész északi (és déli) félteke 64 részre van felbontva. Ok, de van még 3 szint. Ez azt jelenti, hogy csak szélességben számolva 8^4-en = 4096 részre van osztva a Föld. Az egyenlítő kb. 40e km hosszú, ezért ez az index kb. 10 km-es részekre vágja fel.

Update: egy MVP kolléga, Simon Sabin jelezte, hogy nem 10km a default index felbontás, hanem 2.5km. Ez azért van, mert az egyenlítőt a fenti piramisos ábra alapján a rács kerületére vetítik le, ami négyszer olyan hosszú, mint egy oldal, én pedig egy oldalra számoltam a felbontást.

Ez azért elég durva felbontás, főleg, mivel pont ebben a nagyságrendben szűrtünk a segítségével. Ennek ellenére nem lettek fals adatok a kimenetben. Miért? A végrehajtási terv bal alsó részén van egy Filter operátor. Ez arra szűr, hogy:

[AdventureWorks].[dbo].[USCity].[geom].STDistance([@la])<(1.000000000000000e+004) [/source] A bal oldali Merge Join-ból 20 sor potyog ki, valójában ennyit adott vissza az index, mivel durva a felbontása. A Filter és Nested Loop Join után már csak 10 sor maradt, ami már a helyes kimenet. Azaz igaz, hogy az index durva felbontása miatt jöttek be felesleges sorok, de nem baj, 20 sorból mégis csak könnyeb kiválasztani a jókat a lassú függvény (STDistance) tényleges végrehajtásával, mint az eredeti 34000-ből. Finomkodjunk! Hozzuk létre a maximális felbontású indexet! [source='sql'] create spatial index idx_USCity_Spatial_2 on USCity(geom) using geography_grid with ( grids = (high, high, high, high) --,cells_per_object = 64 ); [/source] Ha az előző, medium index is rajta van a táblán, akkor a szerver nem használja ezt azt indexet, mert nem éri meg neki. Ledobva az előzőt vagy index hinttel ráerőszakolva erre a végrehajtási idő 160 ms körül alakul, ami kb. azonos az előző indexelt megoldással. Azonban a lapolvasások száma az ottani 1700-ról felugrott 4800-ra, ami nem meglepő, hisz jelentősen több adat tárol az indextábla. A végrehajtási tervben az index révén 12 sor jön vissza, azaz csak 2 a potya sor, köszönhető a finom felbontású indexnek. Ellenpróbaként csináltam egy low, low, low, low durva felbontású indexet is, ebben 4x4-esek a rácsok szintenként. Ekkor az index 148 sort válogat le, ebből szűrik le a tényleges 10-et. Ennek végrehajtási teljesítménymutatói nagyon hasonlóak az első indexéhez. Valószínűleg ha sűrű elhelyezkedésű adatokról lenne szó (pl. nem városok, hanem városon belüli házak), akkor viszont egy finomabb index érné meg, a durva miatt túl sok adatot kellene lassú módon szűrni a szervernek. Összegezve látható, hogy szépen lehet játszani, hogy az adatok eloszlásának megfelelően milyen felbontású indexet hozunk létre a spatial adatainknak, így játszthatunk az IO és a CPU költség között valamiféle optimumra. Tök szép otimalizálási munka lehet ez. És ezennel a spatial adatokról szóló újdonságokat lezárom, eleget beszéltem már róluk. Látható, hogy valami teljesen új, nagyon izgalmas dolog költözött be az SQL Serverbe, amivel olyan alkalmazásokat írhatunk, amit előtte nagyon nehéz lett volna hatékonyan implementálni egy sima relációs motoron.

2008.02.12.

LINQ vs. SQL teljesítmény

Az előző cikkemmel csak az volt a célom, hogy megmutassam, hogyan lehet megírni ugyanazt a lekérdezést kétféle módon, a teljesítményüket nem is vizsgátam, mivel érzésre egyik se volt túl lassú.

Laci kommentjében a teljesítmény kérdésre hívta fel a figyelmem, hát megnéztem, mi itt a helyzet. Nos, megúszta a LINQ, pedig nem akartam neki reklámot csinálni. Pontosan ugyanolyan teljesítményű lett a két megoldás, ami nem csoda, hisz pontosan ugyanaz az SQL végrehajtási tervet eredményezik! Egyetlen különbség, hogy a sorszámozást LINQ esetén csak procedurálisan tudtam megcsinálni, így a LINQ sql-es kódjában az nem szerepel, de ennek költsége nem is jelent meg a tiszta SQL megoldás végrehajtási tervében, annyira kicsi.

A lényeg tehát, hogy a LINQ nem feltétlenül lassú, sőt, teljesen egyenértékű lehet a hagyományos SQL-es megoldással. De miért is lenne más? Hisz egyszerűen arról van szó, hogy másképp írom le ugyanazt a specifikációt, az egész hatékonysága azon múlik, mennyire okos a LINQ to SQL sqlgenerátora. A jelek szerint egyszerűbb lekérdezésekre tökéletes.

Aki nem hiszi amit írok, nézze meg az alábbi képet (rákattintva nagyban).

LINQ vs SQL teljesítmény

2008.02.11.

LINQ vs. SQL

Filed under: .NET,Adatbázisok,ADO.NET,C#,Linq,SQL Server,SQL Server 2005,Szakmai élet — Soczó Zsolt @ 23:13

Melyik a szimpatikusabb?

select bucid, score, countMatchedEcid, ROW_NUMBER() 
OVER(ORDER BY score DESC) AS 'rank' 
from (
select 
b.ucid as bucid,
a.ucid as aucid, 
sum(w.weight) as score,    
count(*) as countMatchedEcid
from EcidNameValueSummary a, 
genecidparts b, 
weights w 
where a.id=b.id 
and a.value=b.value 
and a.ucid!=b.ucid 
and w.id=a.id 
and w.allowed=1 
and w.limit>=a.countEcids 
and a.ucid=@ucid 
group by b.ucid, a.ucid
) as hits
var matchQuery = from t in
    (from a in c.EcidNameValueSummaries
    join b in c.genecidparts
    on a.id equals b.id
    join w in c.Weights
    on a.id equals w.id
    where w.allowed == 1
    && w.limit >= a.countEcids
    && a.value == b.value
    && a.ucid != b.ucid
    && a.ucid == ucid
    select new
    {
        bucid = b.ucid,
        aucid = a.ucid,
        score = w.weight1
    })
group t by t.bucid into g
orderby g.Sum(e => e.score) descending
select new RankEntity
{
    Ucid = g.Key,
    Score = g.Sum(e => e.score) ?? 0,
    CountMatched = g.Count(),
    Rank = 0
};


BindingListCollection<RankEntity> ranks = 
new BindingListCollection<RankEntity>();
int i = 1;
//It would be cool to do this with linq, but...
foreach (RankEntity e in matchQuery)
{
    e.Rank = i++;
    ranks.Add(e);
}
return ranks;

És emellett, a ROW_NUMBER-t át tudná nekem valaki fordítani LINQ-ra?

Az IT bírálata

Filed under: Élet,Személyes — Soczó Zsolt @ 13:54

Apa, ha nem lenne laptopod mindig ráérnél.

Persze, ez nem biztos, hogy az IT kritikája…

2008.02.10.

Őstermelők és egyéb farmtulajdonosok figyelmébe: MSDeploy

Filed under: IIS,IIS7,Szakmai élet — Soczó Zsolt @ 15:05

Az IIS7-ben van ugye a közös konfig, amit előreláthatóan demózni fogok majd márciusban a Launch-on. Ehhez már csak egy dolog kellett a webfarmoláshoz, a tartalom szinkronizálásának lehetősége. Most már ez is egyenesben van. Gratula az IIS7 bandának, tehetséges bagázs ez. Igyeszek összerakni egy olyan demót, amiben lesz több gép, shared config és MSDeploy is. Ezúttal igyekszek nem szívatni magam, mint az előző előadás során.

2008.02.07.

IIS 7 – App Pool Isolation

Filed under: IIS7,Szakmai élet — Soczó Zsolt @ 02:38

Szerintem ez zseniális.

2008.02.06.

SQL Server 2008 újdonságok 19. – térbeli adattípusok 6.

Filed under: Adatbázisok,SQL Server 2008,Szakmai élet — Soczó Zsolt @ 00:56

Kisebb elhavazós kihagyás után, szépen alszanak a gyerekek (némelyik), folytassuk hát a spatial adatokkal még egy kicsit. Ígértem, hogy valós adatokkal fogunk dolgozni. Ilyen adatokat hatalmas mennyiségben lehet találni a weben, csak persze nem Magyarországról. :)

Természetesen USA-hoz van a legtöbb. Lássunk párat:
Az államok határai és azon belüli területi bontás.
Általános iskolák.
Szavazókörök, stb. sok egyéb adat még.

Magyarországhoz és a környezetéhez innen nyertem ki adatokat. A térképen ki kell jelölni, mely területről kell infó, Next, Next, mely objektumok érdekelnek (ország körvonalak, folyók, városok, stb.), majd Generate File. A kimenet egy ún. ShapeFile, amelyet beimportálhatunk az SQL Serverbe. Hogyan?

Bátrabbak nekiállhatnak egy SSIS csomagot írni, lustábbak, mint én google-öznek, és találnak. Ez a kis jószág, Shape2SQL.exe ShapeFile-okat tud begyúrni SQL táblákba.

ShapeFile import adatbázisba

Az adatokat geography típusként érdemes beimportálni, mert szélesség-hosszúság adatokat töltöttünk le, és a 4326-os SRID is jó, mert abban vannak az adatok.
A következő táblákkal fogunk dolgozni:
-Contry: országhatárok
-City: főbb városok
-River: folyók
-WaterBody: állóvizek, értsd Balaton. :)
-Road: utak.

Fontos tudni, hogy az ingyenesen letölthető adatok szándékosan nagyon durva adatokat tartalmaznak, tessék fizetni a részletes térképekért. Ezt csak azért mondom, mert ez alapvetően befolyásolni fogja a kimenetek hitelességét.

No, kérdezzünk le. Válogassuk le a magyar városokat. Az adataimban nem csak Magyarország van benne, hanem a környező országokból is ez+az, így a lekérdezés jogos. Már kérdés, csak én vagyok ilyen idióta, hogy a földrajzi adatokból akarok ezt a listát előállítani. :)

select CITY_NAME
from City
where geom.STIntersects(
(select geom
from Country
where CNTRY_NAME = N'Hungary')) = 1

A Country táblából kiválasztjuk Mo. körvonalát, ez és a városok közül azokat válogatjuk ki, amelyek metszik az országot. A városok egyébként ebben az adatbázisban pontként vannak reprezentálva.

CITY_NAME
------------------------------
Salgotarjan
Miskolc
Nyiregyhaza
Eger
Gyor
Tatabanya
Debrecen
Budapest
Szombathely
Szekesfehervar
Szolnok
Veszprem
Kecskemet
Zalaegerszeg
Bekescsaba
Kaposvar
Szekszard
Szeged
Pecs
Arad
Pozsony

Az utolsó két bejegyzés csak vicc. :)

Mely városok vannak a Duna 10km-es körzetében?

declare @danube geography = geography::STPointFromText(‘POINT(0 0)’, 4326);

select
–geom.ToString()
–,*
@danube = @danube.STUnion(geom)
from River
where NAME = N’Danube’

select @danube.ToString()

select CITY_NAME,
geom.ToString() ‘A város eredeti adata’,
geom.STStartPoint().ToString() ‘A város mint pont’,
geom.STStartPoint().STDistance(@danube) ‘Távolság a folyótól’
from City
where geom.STStartPoint().STDistance(@danube) < 10000 [/source] [source='c'] CITY_NAME A város eredeti adata A város mint pont Távolság a folyótól ---------------------------------------- ---------------------------------------- ---------------------------------------- ---------------------- Bratislava MULTIPOINT ((48.15000118311 17.129999448 POINT (48.15000118311 17.129999448299998 1691.81121899415 Budapest MULTIPOINT ((47.51499918311 19.093999448 POINT (47.51499918311 19.093999448299996 1167.59360136753 Belgrade MULTIPOINT ((44.79968218311 20.412555448 POINT (44.79968218311 20.412555448299997 5289.83252090268 Drobeta- Turmu Sererin MULTIPOINT ((44.63800018311 22.656000448 POINT (44.63800018311 22.656000448300006 2010.83235902907 Vienna MULTIPOINT ((48.202118183109995 16.32098 POINT (48.202118183109995 16.32098544830 9002.0262024942 [/source] Kicsit hekkelős lett a megoldás. A folyók sok darabban vannak letárolva a River táblában, ezért az STUnion-nal össze kell őket rakni. Igen ám, de az skaláris függvény, nekünk meg aggregálni kellene. Mivel nincs STUnionAggregate (majd írok egyet valamelyik nap), azért marad a select hekk, vagy cursor. A 0,0-ra inicializálás azért kell, mert NULL.STUnion(akármi) az NULL. Ha pont az egyenlítőn és 0 szélességnél lenne adatunk, akkor cumi, mert a mesterséges adat oda esik. Kell majd ide egy rendes CLR aggregáló fv. Az STStartPoint azért kell, mert az STDistance megköveteli, hogy az egyik szereplő pont legyen. A City táblában a városok multipontként vannak felvéve, de csak 1 pontot tartalmaznak. Ezzel gyakorlatilag multipont->pont konverziót csináltam. Az STDistance a mininális távolságot adja meg egy pont és egy alakzat között, így annak használata érthető.

Magyar városok egymástól való távolság-mátrixa (régi útikönyvekben volt ilyen, de persze nem légvonalban, mint nálam):

select
c1.CITY_NAME ‘Kiinduló város’,
c2.CITY_NAME ‘Cél város’,
cast(c1.geom.STStartPoint().STDistance(c2.geom) as int) ‘Távolság [m]’
from City c1
cross join
City c2
where c1.CNTRY_NAME = ‘Hungary’
and c2.CNTRY_NAME = ‘Hungary’
and c1.ID < c2.ID order by c1.CITY_NAME, c2.CNTRY_NAME [/source] [source='c'] Kiinduló város Cél város Távolság [m] ------------------------------ ------------------------------ ------------- Bekescsaba Kaposvar 256101 Bekescsaba Szekszard 186865 Bekescsaba Szeged 86001 Bekescsaba Pecs 231001 Budapest Szombathely 189239 Budapest Szekesfehervar 62993 Budapest Szolnok 91135 Budapest Veszprem 101121 Budapest Kecskemet 81505 Budapest Zalaegerszeg 186420 Budapest Bekescsaba 178882 Budapest Kaposvar 162033 Budapest Szekszard 133373 Budapest Szeged 161716 Budapest Pecs 173280 Debrecen Budapest 191815 Debrecen Szombathely 380340 Debrecen Szekesfehervar 246982 ... [/source] Milyen messze van egymástól a 10 legtávolabbi településpár? [source='sql'] select top 10 with ties c1.CITY_NAME 'Kiinduló város', c2.CITY_NAME 'Cél város', cast(c1.geom.STStartPoint().STDistance(c2.geom) as int) 'Távolság [m]' from City c1 cross join City c2 where c1.CNTRY_NAME = 'Hungary' and c2.CNTRY_NAME = 'Hungary' and c1.ID < c2.ID order by 3 desc [/source] [source='c'] Kiinduló város Cél város Távolság [m] ------------------------------ ------------------------------ ------------- Nyiregyhaza Szombathely 391756 Nyiregyhaza Zalaegerszeg 388659 Debrecen Szombathely 380340 Debrecen Zalaegerszeg 371748 Nyiregyhaza Kaposvar 346639 Szombathely Bekescsaba 346612 Nyiregyhaza Pecs 338276 Miskolc Zalaegerszeg 329734 Miskolc Szombathely 328254 Zalaegerszeg Bekescsaba 326055 [/source] Szemmel láthatóan Nyíregyháza a világ vége. Most némi alvás következik, aztán folytatjuk. :)

2008.02.04.

Bálint, a pacifista

Filed under: Élet,Személyes — Soczó Zsolt @ 09:14

Ma reggel az óvodában.

Mikor beértünk, odajött hozzánk egy kis-kisfiú a folyosón, a pisztolyát csattogtatva. Bálintot nagyon zavarta, ezért beszéltem a kicsihez is, meg hozzá is.
Mondja a kicsi: nézd, nekem van pisztolyom.
Bálint: nekem meg csipegetős csibém.

Elővett a kisfiú egy másik pisztolyt is. Mondom Bálintnak, nézd, ez a kisfiú nagy pisztolykedvelő ember.
-Én meg a növényeket szeretem.

Nagyon büszke vagyok a fiamra, mégha néha kutyaszar rossz is. :)

2008.02.01.

Honnan lehet tudni, hogy az SQL Server kész a recoveryvel?

Egy nagyon érdekes kérdést tettek fel a belső SQL Server MVP newsgroupon. Tegyük fel van egy windows szervizem, ami ugyanazon a gépen fut, mint az SQL Server. Ha az SQL Server észhez tér, el kell indulni a szerviznek. A szervizek között lehet dependency-t létrehozni, de ez nem jó, mert már az SQL Server mint szerviz már fut, attól még nem lehet használni, mert fut az induló recovery folyamat. Hogyan lehet detektálni, kész a recovery?
A primitív megoldás, hogy próbálkozgatunk becsatlakozni. Gagyi.
A szellemes megoldás a következő. Az SQL Server létrehoz egy Named Event-et, és ezt signaled állapotba hozza, ha az összes adatbázis recovery-je megtörtént. Process Explorerrel megnézve nálam ez az event neve:
\sqlserverRecComplete$SQL2008. SQL2008 az instance neve, innen a dollár utáni rész.

Azaz, a szerviznek csak rá kell szinkronizálni erre az eventre, és máris pontosan tudjuk, mikortól él a szerver. Hát nem zseniális?

« Older Posts

Powered by WordPress