2010-11-30 12 views
9

J'ai un problème avec un script qui expire lors de l'extraction de données à partir d'une requête sur une grande table. Le tableau comprend 9 521 457 lignes.Délai d'expiration de la connexion sur requête sur une grande table

La requête que je suis en train de préforme est:

SELECT * 
FROM `dialhistory` 
WHERE `customerId` IN (22606536, 22707251, 41598836); 

Cette requête fonctionne sans problème sur HeidiSQL et prendre environ 171 secondes, puis 434 lignes. Mais quand j'exécute mon script C#, dosez le délai après 161 lignes.

16:54:55: Row 1 
... 
16:54:55: Row 161 
16:55:32: Error -> Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. 

Voici le code

public MySqlDatabase(string server, string database, string username, string password) 
{ 
    ConnectionString = "SERVER=" + server + ";DATABASE=" + database + ";UID=" + username + ";PASSWORD=" + password + ";"; 

} 

public IQueryable<DailHistory> GetHistory(IList<int> customerIds) 
{ 
    IList<DailHistory> list = new List<DailHistory>(); 
    var connection = new MySqlConnection(ConnectionString); 
    connection.Open(); 
    var command = connection.CreateCommand(); 
    command.CommandText = "SELECT * FROM `dialhistory` WHERE `customerId` in ("+string.Join(",", customerIds.ToArray())+")"; 
    var reader = command.ExecuteReader(); 
    int i = 1; 
    while (reader.Read()) 
    { 
     Console.WriteLine(DateTime.Now.ToLongTimeString() + ": Row " + i); 
     i++; 
     try 
     { 
      var d = new DailHistory(); 
      d.CustomerId = int.Parse((string) reader["customerId"]); 
      d.Agent = ParseNullAbleString(reader["agent"].ToString()); 
      d.CallBackReason = ParseNullAbleString(reader["callBackReason"].ToString()); 
      d.CallState = ParseCallSate(reader["callState"].ToString()); 
      d.ContactResponse = ParseNullAbleString(reader["contactResponse"].ToString()); 
      d.DailTime = new DailTime(reader["dialStart"].ToString(), reader["dialEnd"].ToString()); 
      d.HistoryIndex = int.Parse(reader["historyIndex"].ToString()); 
      d.Note = ParseNullAbleString(reader["note"].ToString()); 
      d.OldDialNo = ParseNullAbleInt(reader["oldDialNo"].ToString()); 
      d.ProjectJob = ParseNullAbleString(reader["projectJob"].ToString()); 
      list.Add(d); 
     } 
     catch(Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 
    } 
    reader.Close(); 
    return list.AsQueryable(); 
} 

Répondre

22
command.CommandTimeout = int.MaxValue; 

Si vous en savez plus exactement le numéro à insérer, à le faire. Si vous le définissez sur int.MaxValue, vous supprimez une barrière de sécurité.

12

Réglez le CommandTimeout sur l'objet de commande

var command = connection.CreateCommand(); 
command.CommandTimeout = 0; 
//zero specifies never timeout. 
//Any number greater than zero is the number of seconds before 
//the command will time out. 
+0

command.CommandTimeout = 0; n'a pas fonctionné :(il a toujours expiré – Androme

+1

@DoomStone Votre base de données peut avoir un délai d'attente défini, lorsque vous demandez le délai d'attente en utilisant commandTimeout, cela peut être annulé par la configuration de la base de données, dans mon cas cela a fonctionné pour moi un problème que vous avez besoin de travailler avec votre DBA .. (pour les futurs lecteurs .. évidemment votre problème était il ya des années désolé) – Chris

2

Ajouter un index sur la colonne customerId.

+0

Il y a, c'est la clé primaire! – Androme

+1

@DoomStone - Je ne vois pas comment cela peut éventuellement prendre 171 secondes pour renvoyer 434 lignes alors, vous renvoyez des données extrêmement larges (par exemple BLOBs) Et 'CustomerId' ne peut pas être le PK seul de toute façon si 3 customerids retournent 434 lignes.Quelles sont les autres colonnes de l'index et que –

+1

Voulez-vous dire que c'était la clé primaire d'une autre table? Si c'était la clé primaire sur cette table, vous ne devriez pas obtenir 434 lignes retournées à partir de votre requête. – whudson05

0
command.CommandTimeout = 2147483; 

La plus grande valeur pour un délai d'attente de commande MySQL est la plus grande valeur pour un entier de 32 bits, en millisecondes, 2147483647. Mais en C# la propriété CommandTimeout est en secondes, pas millisecondes, donc plus haut que 2.147.483 entraînera dans une exception.

Bien que ce ne soit pas infini, il est de 24 jours, 20 heures, 31 minutes et 23 secondes, ce qui, nous l'espérons, répondra à vos besoins.

La définition de la valeur à 0 ne fonctionnait pas pour moi. La propriété CommandTimeout ne conserverait pas la valeur de 0 et continuerait à revenir automatiquement à 30.

La définition de la valeur -1 semblait fonctionner, mais je ne l'ai pas testée suffisamment pour être certain qu'un délai d'attente ne serait jamais se produire.

option la plus sûre: aller avec 2147483.