{"id":1210,"date":"2012-03-30T09:08:08","date_gmt":"2012-03-30T08:08:08","guid":{"rendered":"http:\/\/soci.hu\/blog\/?p=1210"},"modified":"2012-04-03T12:35:53","modified_gmt":"2012-04-03T11:35:53","slug":"sql-server-2012-ujdonsagok-2-sequence","status":"publish","type":"post","link":"https:\/\/soci.hu\/blog\/index.php\/2012\/03\/30\/sql-server-2012-ujdonsagok-2-sequence\/","title":{"rendered":"SQL Server 2012 \u00fajdons\u00e1gok &#8211; 2. Sequence"},"content":{"rendered":"<p>Update:<br \/>\nA cikkben NEM folytonos sorsz\u00e1mgener\u00e1l\u00e1sr\u00f3l \u00edrok, mint pl. amit sz\u00e1mla sorsz\u00e1moz\u00e1sn\u00e1l haszn\u00e1lnak, hanem puszt\u00e1n egyedi kulcsok gener\u00e1l\u00e1s\u00e1t, amik nem ism\u00e9tl\u0151dnek, monoton n\u0151nek, de nem folytonosak.<\/p>\n<p>A sorsz\u00e1mgener\u00e1l\u00e1s igen \u00e1ltal\u00e1nos feladat adatb\u00e1zisalap\u00fa alkalmaz\u00e1sokban. Az egyik leggyakoribb eset, amikor eg\u00e9sz sz\u00e1mokra \u00e9p\u00edtett mesters\u00e9ges els\u0151dleges kulcsoknak kell \u00e9rt\u00e9ket gener\u00e1lni. Erre eddig a leggyakrabban alkalmazott megold\u00e1s az IDENTITY-vel megjel\u00f6lt oszlop haszn\u00e1lata volt. IDENTITY-n\u00e9l az oszlopon kijel\u00f6lt sorsz\u00e1mgener\u00e1l\u00e1s \u00e9s az insert m\u0171velet \u00f6ssze volt ragadva. A SEQUENCE nev\u0171 \u00faj adatb\u00e1zis objektum seg\u00edts\u00e9g\u00e9vel mindent\u0151l teljesen f\u00fcggetlen sorsz\u00e1mgener\u00e1torokat hozhatunk l\u00e9tre, amelyeket b\u00e1rmikor megh\u00edvhatunk, nem csak insertekhez.<br \/>\nMi\u00e9rt j\u00f3 ez a sorsz\u00e1mgener\u00e1l\u00e1s \u00e9s a felhaszn\u00e1l\u00e1sa elv\u00e1laszt\u00e1sa? K\u00e9pzelj\u00fck el azt az estet, hogy el kell menteni megrendel\u00e9seket. Van 1000 megrendel\u00e9s fejl\u00e9c\u00fcnk (Order Header), \u00e9s mindegyikhez van \u00e1tlagban 5 megrendel\u00e9s t\u00e9tel (Order Detail). IDENTITY -t haszn\u00e1lva egyes\u00e9vel be kell sz\u00farni a fejl\u00e9c sorokat, visszavezetni az adatel\u00e9r\u0151 r\u00e9tegbe a gener\u00e1lt identity \u00e9rt\u00e9ket, \u00e1t\u00edrni az adott fejl\u00e9c al\u00e1 tartoz\u00f3 megrendel\u00e9s t\u00e9telek sz\u00fcl\u0151 fejl\u00e9cre mutat\u00f3 idegen kulcs\u00e1t a kapott \u00e9rt\u00e9kkel, majd besz\u00farni a megrendel\u00e9s t\u00e9teleket. A megrendel\u00e9s t\u00e9teleket be lehet sz\u00farni egy batch-ben, azaz egy k\u00f6r\u00fclfordul\u00e1s alatt. Azonban a fejl\u00e9c sorok identity-j\u00e9nek visszavezet\u00e9se miatt 1000 k\u00fcl\u00f6n batch-et kell bek\u00fcldeni a sz\u00fcl\u0151 sorok besz\u00far\u00e1s\u00e1hoz, majd tov\u00e1bbi 1000-et a gyerek sorok kedv\u00e9\u00e9rt. Ez \u00f6sszesen 2000 h\u00e1l\u00f3zati k\u00f6r\u00fclfordul\u00e1s, pedig m\u00e1r k\u00f6tegelt\u00fck a gyerekek besz\u00far\u00e1s\u00e1t, e n\u00e9lk\u00fcl 1000+5000=6000 k\u00f6r\u00fclfordul\u00e1s lenne. Ha egy h\u00e1l\u00f3zati k\u00f6r\u00fclfordul\u00e1s 10ms (ez realisztikus, \u00e9s mag\u00e1ban foglalja az insert idej\u00e9t is), akkor a 2000 m\u0171velet 20 m\u00e1sodperc alatt fut le.<br \/>\nHa azonban SEQUENCE seg\u00edts\u00e9g\u00e9vel gener\u00e1ljuk a kulcsokat, akkor az adatel\u00e9r\u0151 r\u00e9teg minden tov\u00e1bbi n\u00e9lk\u00fcl lek\u00e9rhet egy nagyobb sorsz\u00e1mtartom\u00e1nyt, azaz nem 1-gyel l\u00e9pteti el\u0151re a SEQUENCE-t, hanem pl. 10000-rel.  \u00cdgy az az adatel\u00e9r\u0151 r\u00e9teg kap 10000 sorsz\u00e1mot, amit m\u00e1s garant\u00e1ltan nem kap meg, \u00edgy ezzel \u0151 gazd\u00e1lkodhat. Mit fog tenni egy okos az adatel\u00e9r\u0151 r\u00e9teg? El\u0151re kiosztja minden sz\u00fcl\u0151 sornak a kulcs\u00e9rt\u00e9ket a kapott tartom\u00e1nyb\u00f3l, ut\u00e1na \u00e1ll\u00edtja a gyerekeket, \u00e9s 1 azaz egy batch-ben k\u00e9pes besz\u00farni az \u00f6sszes sz\u00fcl\u0151 \u00e9s gyerek sort! Praktikusan ez azt jelenti, hogy val\u00f3sz\u00edn\u0171leg 1 mp-en bel\u00fcl besz\u00far\u00e1sra ker\u00fcl mind a 6000 sor.<br \/>\n\u00d3ri\u00e1si nyeres\u00e9g ez, amelyet a fejlettebb Objektum Rel\u00e1ci\u00f3s Mapper-ek (pl. NHibernate) HiLo strat\u00e9giak\u00e9nt ismernek, \u00e9s tudnak SEQUENCE-t haszn\u00e1lni a kiosztott id-k (els\u0151dleges kulcsok) kezel\u00e9s\u00e9re.<br \/>\nA megold\u00e1s kulcsa teh\u00e1t az, hogy m\u00e9g a sorok besz\u00far\u00e1sa el\u0151tt tudunk azoknak id-t gener\u00e1lni, ez\u00e1ltal extra optimaliz\u00e1l\u00e1si lehet\u0151s\u00e9geink vannak. Minek k\u00f6sz\u00f6nhet\u0151 ez? Annak, hogy az id gener\u00e1l\u00e1s \u00e9s a besz\u00far\u00e1s m\u0171veletek nincsenek \u00f6sszek\u00f6tve id\u0151ben, k\u00f6sz\u00f6nhet\u0151en a SEQUENCE-eknek.<br \/>\nMivel a SEQUENCE \u00e1ltal gener\u00e1lt sorsz\u00e1mot tetsz\u00e9s szerint haszn\u00e1lhatjuk, k\u00e9sz\u00edthet\u00fcnk vele p\u00e9ld\u00e1ul t\u00e1bl\u00e1k k\u00f6z\u00f6tt megosztott id gener\u00e1tort is, \u00edgy p\u00e1r t\u00e1bla \u00fagy kap els\u0151dleges kulcsot, hogy a t\u00e1bl\u00e1k k\u00f6z\u00f6tt n\u00e9zve se lesz \u00fctk\u00f6z\u00e9s k\u00f6z\u00f6tt\u00fck.<br \/>\nN\u00e9zz\u00fcnk p\u00e1r p\u00e9ld\u00e1t r\u00e1.<br \/>\nInteger alap\u00fa SEQUENCE l\u00e9trehoz\u00e1s, amely 1-t\u0151l indul \u00e9s 1-es\u00e9vel l\u00e9pked:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate sequence HumanResources.Sequence1 as int\r\nstart with 1\r\nincrement by 1;\r\n<\/pre>\n<p>A k\u00f6vetkez\u0151 sorsz\u00e1m lek\u00e9r\u00e9se:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect next value for HumanResources.Sequence1;\r\n<\/pre>\n<p>Tr\u00fckk\u00f6sebb SEQUENCE-ek is vannak, amelyek miut\u00e1n el\u00e9rek egy fels\u0151 hat\u00e1rt, \u00e1tfordulnak, \u00e9s \u00fajrakezdik a sz\u00e1ml\u00e1l\u00e1st:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate sequence HumanResources.SequenceWithCycle\r\nas int\r\nstart with 1\r\nincrement by 1\r\nminvalue 1\r\nmaxvalue 5\r\ncycle;\r\n<\/pre>\n<p>Miut\u00e1n ell\u00e9pkedett 5-ig, \u00fajra 1 lesz a k\u00f6vetkez\u0151 gener\u00e1lt \u00e9rt\u00e9k. A cycle kulcssz\u00f3 n\u00e9lk\u00fcl hib\u00e1t kapn\u00e1nk az 5 ut\u00e1n megh\u00edvott next value-ra:<\/p>\n<p>The sequence object &#8216;SequenceWithCycle&#8217; has reached its minimum or maximum value. Restart the sequence object to allow new values to be generated.<\/p>\n<p>Hogyan implement\u00e1lt\u00e1k a SEQUENCE-t, hogy el\u00e9g gyors legyen? Ha tiszt\u00e1n mem\u00f3ri\u00e1ban n\u00f6velgetn\u00e9k a sorsz\u00e1mot, akkor a sorsz\u00e1m a szerver \u00fajraindul\u00e1sa ut\u00e1n \u00fajraindulna, ez\u00e9rt mindenk\u00e9ppen kell valamilyen tart\u00f3s t\u00e1rol\u00f3 (diszk, sql t\u00e1bla, stb.) m\u00f6g\u00e9. Lehetne azt csin\u00e1lni, hogy amikor le\u00e1ll\u00edtj\u00e1k a szervert, akkor ki\u00edrn\u00e1k az sz\u00e1ml\u00e1l\u00f3 \u00e1ll\u00e1s\u00e1t, majd \u00fajraind\u00edt\u00e1s ut\u00e1n visszaolvass\u00e1k azt. Ezzel viszont az a baj, hogy ha v\u00e1ratlanul lehal a szerver processz, vagy elmegy az \u00e1ram, akkor nem lesz ki\u00edrva az utols\u00f3 \u00e9rt\u00e9k, \u00edgy legk\u00f6zelebb \u00fajra kioszt m\u00e1r kiadott sorsz\u00e1mokat, ami nyilv\u00e1nval\u00f3 logikai hib\u00e1kat okozna.<br \/>\nLehetne minden sorsz\u00e1m let\u00e9p\u00e9se ut\u00e1n ki\u00edrni az aktu\u00e1lis \u00e9rt\u00e9ket, de ez meg nagyon lass\u00fa lenne. A SQL Server \u00e1ltal v\u00e1lasztott megold\u00e1s kompromisszum a k\u00e9t oldal k\u00f6z\u00f6tt, egyfajta cache-el\u00e9s.<br \/>\nMem\u00f3ri\u00e1ban t\u00e1rolja sorsz\u00e1mot, de \u00fagy, hogy egyszerre lek\u00e9r egy nagyobb tartom\u00e1nyt diszkr\u0151l, \u00e9s azt osztogatja ki, tiszt\u00e1n mem\u00f3ri\u00e1ban. Mikor elfogyott a tartom\u00e1ny, akkor megint n\u00f6vel egy nagyobb harap\u00e1st rajta, ki\u00edrja a diszkre, \u00e9s elkezdi \u00fajra mem\u00f3ri\u00e1b\u00f3l osztani. Mi t\u00f6rt\u00e9nik, ha elhasal a szerver? Csak annyi, hogy p\u00e1r sorsz\u00e1m, ami m\u00e9g nem ker\u00fclt kioszt\u00e1sra a lek\u00e9rt tartom\u00e1nyb\u00f3l kimarad, \u00e9s elkezd egy \u00faj tartom\u00e1nyt osztani a szerver. Luk lesz a sorsz\u00e1mokban, de ez nem okoz probl\u00e9m\u00e1t, se az IDENTITY-n\u00e9l, sem a SEQUENCE-n\u00e9l nem \u00e9p\u00edthet\u00fcnk a folytonos sorsz\u00e1mokra, csak azt garant\u00e1lj\u00e1k, hogy k\u00e9tszer nem adj\u00e1k ki ugyanazt a sorsz\u00e1mot.<br \/>\nA SQUENCE l\u00e9trehoz\u00e1sakor meg lehet adni, mekkora tartom\u00e1nyt haszn\u00e1ljon cache-k\u00e9nt:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ncreate sequence HumanResources.SequenceWithLargerCache\r\nas int\r\nstart with 1\r\nincrement by 1\r\ncache 100;\r\n<\/pre>\n<p>Kis cache eset\u00e9n kicsi a val\u00f3sz\u00edn\u0171s\u00e9ge a luknak, nagy cache eset\u00e9n gyorsabb a sorsz\u00e1moszt\u00e1s. \u00c9rtelemszer\u0171en intenz\u00edv SEQUENCE haszn\u00e1l\u00f3 programokn\u00e1l \u00e9rdemes nagy cache \u00e9rt\u00e9ket haszn\u00e1lni, de \u00e9rdekes m\u00f3don p\u00e1r 10-es m\u00e9ret ut\u00e1n m\u00e1r nem \u00e9rhet\u00fcnk el jelent\u0151s nyeres\u00e9get.<br \/>\nA SEQUENCE-eket nem csak egyes\u00e9vel lehet l\u00e9ptetni, p\u00e9ld\u00e1ul a kor\u00e1bban le\u00edrt HiLo id gener\u00e1tor adatel\u00e9r\u0151 strat\u00e9gia egyszerre p\u00e1r sz\u00e1z vagy ezer sorsz\u00e1mot k\u00e9r mag\u00e1nak, amivel azt\u00e1n maga gazd\u00e1lkodik. Tetsz\u0151leges sz\u00e1m\u00fa el\u0151rel\u00e9ptet\u00e9st \u00edgy kell k\u00e9rni:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\ndeclare @RangeFirstValue sql_variant ;\r\ndeclare @RangeLastValue sql_variant ;\r\n\r\nexec sp_sequence_get_range\r\n@sequence_name = N&#039;HumanResources.CounterSeq&#039;\r\n, @range_size = 50\r\n, @range_first_value = @RangeFirstValue output\r\n, @range_last_value = @RangeLastValue output;\r\n\r\nSELECT @RangeFirstValue, @RangeLastValue;\r\n<\/pre>\n<p>Kimenet: 2336 2385<\/p>\n<p>A SEQUENCE egy\u00e9bk\u00e9nt m\u00e1s adatb\u00e1zisokr\u00f3l val\u00f3 \u00e1tt\u00e9r\u00e9skor (Oracle, Firebird) az egyik legprobl\u00e9m\u00e1sabb pont volt, SQL Server 2012-t\u0151l ez is megold\u00f3dott.<br \/>\nA m\u00e1sik probl\u00e9m\u00e1s pont a soronk\u00e9nt m\u0171k\u00f6d\u0151 triggerek, de ebben nem l\u00e9pett el\u0151re a 2012.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update: A cikkben NEM folytonos sorsz\u00e1mgener\u00e1l\u00e1sr\u00f3l \u00edrok, mint pl. amit sz\u00e1mla sorsz\u00e1moz\u00e1sn\u00e1l haszn\u00e1lnak, hanem puszt\u00e1n egyedi kulcsok gener\u00e1l\u00e1s\u00e1t, amik nem ism\u00e9tl\u0151dnek, monoton&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,4,30,78],"tags":[],"class_list":["post-1210","post","type-post","status-publish","format-standard","hentry","category-adatbazisok","category-szakmai-elet","category-sql-server","category-sql-server-2012"],"_links":{"self":[{"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1210","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=1210"}],"version-history":[{"count":3,"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1210\/revisions"}],"predecessor-version":[{"id":1219,"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/posts\/1210\/revisions\/1219"}],"wp:attachment":[{"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=1210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=1210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/soci.hu\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=1210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}