Sledujte ma na Twitteri

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 users)

  1. internal static void ProcessUsers(List users){
  2. DateTime d = new DateTime();
  3. foreach (LdapUser user in users)
  4. {
  5. User dbUser = (from u in db.Users where u.dxrUid == user.dxrUid select u).SingleOrDefault();
  6. if (dbUser==null) {
  7. dbUser = new User();
  8. db.Users.InsertOnSubmit(dbUser);
  9. ...
  10. db.SubmitChanges();
  11. }
  12. UserInTime dbUserInTime = (from ut in db.UserInTimes where ut.UserId == dbUser.Id orderby ut.StartDate descending select ut).FirstOrDefault();
  13. if (dbUserInTime == null)
  14. {
  15. dbUserInTime = new UserInTime();
  16. db.UserInTimes.InsertOnSubmit(dbUserInTime);
  17. dbUserInTime.StartDate = DateTime.Now;
  18. ...
  19. db.SubmitChanges();
  20. } else if (...)
  21. {
  22. UserInTime dbUserInTimeNew = new UserInTime();
  23. ...
  24. db.SubmitChanges();
  25. }
  26. }
  27. }
  28.  
  29.  

Ú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

  1. CompiledQuery.Compile((DataContext, arg0, arg1 ...) => linq query)

teda v našom prípade by to pre výber zamestnanca bolo

  1. 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

  1. internal static class DBQuery
  2. {
  3. 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());
  4. 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());
  5. }

V pôvodnej metóde ostáva už iba nahradiť

  1. User dbUser = (from u in db.Users where u.dxrUid == user.dxrUid select u).SingleOrDefault();
  2. ...
  3. UserInTime dbUserInTime = (from ut in db.UserInTimes where ut.UserId == dbUser.Id orderby ut.StartDate descending select ut).FirstOrDefault();

za

  1. User dbUser = DBQuery.getUser(db, user.dxrUid);
  2. ...
  3. 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.

Sledujte moje články: vybrali.sme.sk Linkuj.cz  

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

RSS komentárovRSS komentárov

Peter Malik (20.08.10 - 19:35:35)

Zaujimavy clanok…a mozem zasa trosku zrychlit aplikaciu :)

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

(povinné)

(povinný,nezverejňuje sa)


Odoslať komentár

Autor

Igor Kulman Igor Kulman at LinkeIn
Igor Kulman at Flick
Igor Kulman at Twitter
Igor Kulman at Posterous

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.

Kategórie

Náhodná referencia

iFaktury

iFaktury