LINQ: zrýchlenie databázových dopytov pomocou Compiled Queries
Kategória: .NET, C#, publikované: 29.05.2010, autor: Igor Kulman
Ak používate .NET a jazyk C#, určite poznáte a hojne využívate aj jednu z jeho hlavných predností, a to LINQ. Použitie LINQ je síce veľmi jednoduché, preklad do SQL pri LINQ to SQL však niečo stojí a pri náročných použitiach môžete pozorovať nízky výkon vašej aplikácie. Odpoveďou na problémy s výkonnosťou sú Compiled Queries.
Majme statickú triedu DB a v nej metódu ProcessUsers(List
internal static void ProcessUsers(List users){ foreach (LdapUser user in users) { User dbUser = (from u in db.Users where u.dxrUid == user.dxrUid select u).SingleOrDefault(); if (dbUser==null) { db.Users.InsertOnSubmit(dbUser); ... db.SubmitChanges(); } UserInTime dbUserInTime = (from ut in db.UserInTimes where ut.UserId == dbUser.Id orderby ut.StartDate descending select ut).FirstOrDefault(); if (dbUserInTime == null) { db.UserInTimes.InsertOnSubmit(dbUserInTime); dbUserInTime.StartDate = DateTime.Now; ... db.SubmitChanges(); } else if (...) { ... db.SubmitChanges(); } } }
Úlohou tejto metódy je pre každého zamestnanca, ktorý príde z LDAPu skontrolovať, či sa záznam o ňom nachádza v DB (ak nie, vytvorí sa) a či sa na ňom niečo zmenilo (ak áno, vytvorenie nového záznamu s platnosťou od aktuálneho času a novými údajmi). Ako si môžete všimnúť, dopyty na získanie zamestnanca a jeho najnovšieho záznamu sa opakujú v každom kroku cyklu, ich opakovaný preklad do SQL a následne vyhodnotenie nie sú práve efektívne.
Správnou optimalizáciou je použitie tzv. Compiled Queries pomocou statickej triedy CompiledQuery a jej metódy Compile, ktorej použitie si môžete predstaviť ako
CompiledQuery.Compile((DataContext, arg0, arg1 ...) => linq query)
teda v našom prípade by to pre výber zamestnanca bolo
CompiledQuery.Compile((DataContext db, string dxrUid) => (from u in db.GetTable<user>() where u.dxrUid == dxrUid select u).SingleOrDefault())
Na takúto Complied Query potom môžeme volať pomocou definovanej funkcie (alebo skôr referencie), najlepšie uzavretej v novej statickej triede
internal static class DBQuery { internal static Func<datacontext,string> getUser = CompiledQuery.Compile((DataContext db, string dxrUid) => (from u in db.GetTable<user>() where u.dxrUid == dxrUid select u).SingleOrDefault()); internal static Func<datacontext,int> getUserInTime = CompiledQuery.Compile((DataContext db, int UserId) => (from ut in db.GetTable<userintime>() where ut.UserId == UserId orderby ut.StartDate descending select ut).FirstOrDefault()); }
V pôvodnej metóde ostáva už iba nahradiť
User dbUser = (from u in db.Users where u.dxrUid == user.dxrUid select u).SingleOrDefault(); ... UserInTime dbUserInTime = (from ut in db.UserInTimes where ut.UserId == dbUser.Id orderby ut.StartDate descending select ut).FirstOrDefault();
za
User dbUser = DBQuery.getUser(db, user.dxrUid); ... UserInTime dbUserInTime = DBQuery.getUserInTime(db,dbUser.Id);
Nárast výkonu môže byť až päťnásobný. Tento postup sa oplatí používať na všetky mnohonásobne opakované dopyty.
Prečo je Java zaostalý a neefektívny jazyk
Java je vraj napopulárenejší programovací jazyk. Prečo, to naozaj nechápem a asi ani nikdy nepochopím.... čítať ďalej
Zmena cudzieho kľúča v LINQ to SQL
Ak používate LINQ to SQL a pri zmene cudzieho kľúča nejakej entity ste narazili na výnimku... čítať ďalej
Komentáre
peter Malik (21.08.10 - 00:47:43)
Pri pouziti .Net Fw 4.0 sa da vyuzit viac jadier
var data = from db in dataDb.DataTbl.AsParallel() where ‚statement‘ orderby ‚statement‘ select db;
Pridať komentár
Autor
Autor je absolventom softvéroveho inžinierstva na Univerzite Karlovej v Prahe, pracuje ako Windows Phone 7 vývojár v Inmite a pôsobil aj ako prispievateľ počítačového magazínu.


RSS komentárov




Peter Malik (20.08.10 - 19:35:35)
Zaujimavy clanok…a mozem zasa trosku zrychlit aplikaciu :)