[SqlServer] Accès multiples et performances

Accès multiples et performances [SqlServer] - SQL/NoSQL - Programmation

Marsh Posté le 26-01-2006 à 12:55:53    

:hello:
 
Ds mon processus de facturation j'ai des stats à faire à partir d'une table qui contient entre 20 et 60 millions d'enregistrements.
Ces stats consistent à faire 'x' requêtes par client, processus répété pour 'y' clients.
Cà fait donc une multitude d'accès à la base.
L'appli qui génére les stats et la base sont sur la même machine.
 
Y aurait il un gain quelconque à faire une seule requête par client qui récupère donc la totalité des enregistrements concernés ( donc 1 seul accès à la base par client ), et à faire le filtrage / calcul par l'appli ?
 
[:spikler]

Reply

Marsh Posté le 26-01-2006 à 12:55:53   

Reply

Marsh Posté le 26-01-2006 à 16:48:46    

normalement, oui.
 
c'est vrai dans tous les cas, pas seulement avec des accès multiples : généralement, une seule requête faut mieu que x, surtout si les x sont relativement similaires et utilisent donc les mêmes index.

Reply

Marsh Posté le 26-01-2006 à 16:50:57    

C'est mon cas : pour chaque client je fais environ une quinzaine de requêtes sur cette table avec des critères différents à chaque fois ...

Reply

Marsh Posté le 26-01-2006 à 16:55:21    

sauf que si c'est "sur cette table", y'a 99,999% que t'utilises plusieurs fois les mêmes indexes ;)
 
tu peux poster quelques exemples de requêtes qu'on voit ce qu'on peut en faire ?

Reply

Marsh Posté le 27-01-2006 à 09:56:22    

Qq exemples :
( attention, mes requêtes sont construites ds l'appli en C#, donc {0} et {1} sont des paramètres propres à chaque client )
 

Code :
  1. // Chargement des tickets 'local'
  2. SELECT
  3. ID_PhoneLine,
  4. ( CONVERT ( VARCHAR ( 50 ), BeginDate, 103 ) + ' ' + CONVERT ( VARCHAR ( 50 ), BeginDate, 108 ) ) AS Da,
  5. CONVERT ( decimal ( 18, 3 ), Price ) AS P,
  6. NumberCalled AS NC,
  7. FormattedDuration AS Du
  8. FROM TicketList
  9. INNER JOIN PhoneLine ON PhoneLine.ID_PhoneLineVoiceInfo = TicketList.ID_PhoneLineVoiceInfo
  10. WHERE ID_Invoice = {0}
  11. AND TicketList.ID_PhoneLineVoiceInfo = {1}
  12. AND ID_NationalCallType = 1
  13. ORDER BY BeginDate
  14. // Cumul des tickets 'local'
  15. SELECT
  16. MIN ( PhoneLine.ID_PhoneLine ) AS ID_PhoneLine,
  17. SUM ( TicketList.Price ) AS SumPrice
  18. FROM TicketList
  19. INNER JOIN PhoneLine ON PhoneLine.ID_PhoneLineVoiceInfo = TicketList.ID_PhoneLineVoiceInfo
  20. WHERE ID_Invoice = {0}
  21. AND TicketList.ID_PhoneLineVoiceInfo = {1}
  22. AND ID_NationalCallType = 1
  23. // Chargement des tickets 'national'
  24. SELECT
  25. ID_PhoneLine,
  26. ( CONVERT ( VARCHAR ( 50 ), BeginDate, 103 ) + ' ' + CONVERT ( VARCHAR ( 50 ), BeginDate, 108 ) ) AS Da,
  27. CONVERT ( decimal ( 18, 3 ), Price ) AS P,
  28. NumberCalled AS NC,
  29. FormattedDuration AS Du
  30. FROM TicketList INNER JOIN PhoneLine ON PhoneLine.ID_PhoneLineVoiceInfo = TicketList.ID_PhoneLineVoiceInfo
  31. WHERE ID_Invoice = {0}
  32. AND TicketList.ID_PhoneLineVoiceInfo = {1}
  33. AND ID_NationalCallType = 2
  34. ORDER BY BeginDate
  35. // Cumul des tickets 'national'
  36. SELECT
  37. MIN ( ID_PhoneLine) AS ID_PhoneLine,
  38. SUM ( Price ) AS SumPrice
  39. FROM TicketList
  40. INNER JOIN PhoneLine ON PhoneLine.ID_PhoneLineVoiceInfo = TicketList.ID_PhoneLineVoiceInfo
  41. WHERE ID_Invoice = {0}
  42. AND TicketList.ID_PhoneLineVoiceInfo = {1}
  43. AND ID_NationalCallType = 2

Reply

Marsh Posté le 27-01-2006 à 10:34:30    

c'est donc bien plusieurs fois les mêmes requête avec un pouillème qui change.
 
plusieurs choses :
1) plutôt que de mettre des {0}, etc. utilise les paramètres (avec l'objet Command). bien plus performant, et garanti l'impossibilité de faire du "sql injection"
2) là, je vois deux requêtes appelées deux fois chacune avec des paramètres différents. crée une vue, ou même une fonction, tu gagneras énormément en perfs

Reply

Marsh Posté le 27-01-2006 à 10:36:00    

Exemple d'utilisation de paramètres (ici avec Oracle, SQL Server diffère légèrement)
 

Code :
  1. // Identification query
  2.  private const string checkRights =  "select tie.codsoc, ut_soc.libut_soc, tie.typtie, tie.sigtie, tie.nomtie, tie.codlan from tie, ut_soc where ut_soc.soc in (2, 3) and tie.codsoc = ut_soc.soc and tie.typtie in ('CLI', 'REP') and tie.codett = 'ACT' and upper(tie.sigtie) = upper(:login) and upper(tie.codzn7) = upper(:password)";
  3.  public bool checkPassword(string login, string password)
  4.  {
  5.   bool loginIsValid;
  6.   if (cnx.isAvailable)
  7.   {
  8.    OracleCommand cmd = cnx.CreateCommand();
  9.    cmd.CommandType = CommandType.Text;
  10.    cmd.CommandText = checkRights;
  11.    OracleParameter param1 = cmd.CreateParameter();
  12.    param1.DbType = DbType.AnsiString;
  13.    param1.Direction = ParameterDirection.Input;
  14.    param1.ParameterName = ":login";
  15.    param1.Size = 12;
  16.    param1.Value = login;
  17.    cmd.Parameters.Add(param1);
  18.    OracleParameter param2 = cmd.CreateParameter();
  19.    param2.DbType = DbType.AnsiString;
  20.    param2.Direction = ParameterDirection.Input;
  21.    param2.ParameterName = ":password";
  22.    param2.Size = 12;
  23.    param2.Value = password;
  24.    cmd.Parameters.Add(param2);
  25.    loginIsValid = (cnx.ExecuteScalar(cmd) != null);
  26.   }
  27.   else
  28.   {
  29.    loginIsValid = false;
  30.   }
  31.   return loginIsValid;
  32.  }

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed