2013-03-17 1 views
0

Je construis une application de magasin basée sur le Web, et je dois gérer de nombreuses sous-catégories imbriquées les unes dans les autres. Le fait est, je n'ai aucune idée si mon script va gérer des milliers (le nouveau système remplacera l'ancien, donc je sais quel trafic je dois attendre) - à l'heure actuelle, le décalage de réponse du serveur local est 1-2 secondes plus que les autres pages avec ajouté environ 30 produits dans différentes catégories.Indexer les sous-catégories plutôt que les trouver dynamiquement (performance)

Mon code est le suivant:

BazaArkadiaDataContext db = new BazaArkadiaDataContext(); 
    List<A_Kategorie> Podkategorie = new List<A_Kategorie>(); 

    public int IdKat { get; set; } 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     if (!IsPostBack) 
     { 
      List<A_Produkty> Produkty = new List<A_Produkty>(); //list of all products within the category and remaining subcategories 

      if (Page.RouteData.Values["IdKategorii"] != null) 
      { 
       string tmpkat = Page.RouteData.Values["IdKategorii"].ToString(); 
       int index = tmpkat.IndexOf("-"); 
       if (index > 0) 
        tmpkat = tmpkat.Substring(0, index); 
       IdKat = db.A_Kategories.Where(k => k.ID == Convert.ToInt32(tmpkat)).Select(k => k.IDAllegro).FirstOrDefault(); 
      } 
      else 
       return; 

      PobierzPodkategorie(IdKat); 

      foreach (var item in Podkategorie) 
      { 
       var x = db.A_Produkties.Where(k => k.IDKategorii == item.ID); 
       foreach (var itemm in x) 
       { 
        Produkty.Add(itemm); 
       } 
      } 

      //data binding here 
     } 
    } 

    List<A_Kategorie> PobierzPodkategorie(int IdKat, List<A_Kategorie> kat = null) 
    { 
     List<A_Kategorie> Kategorie = new List<A_Kategorie>(); 
     if (kat != null) 
      Kategorie.Concat(kat); 

     Kategorie = db.A_Kategories.Where(k => k.KatNadrzedna == IdKat).ToList(); 

     if (Kategorie.Count() > 0) 
     { 
      foreach (var item in Kategorie) 
      { 
       PobierzPodkategorie(item.IDAllegro, Kategorie); 
       Podkategorie.Add(item); 
      } 
     } 
     return Kategorie; 
    } 

TMC; DR *

Ma fonction PobierzPodkategorie cherche récursive dans les sous-catégories (sous-catégorie a KatNadrzedna colonne pour sa catégorie parente, qui est placé dans IDAllegro) , sélectionne tous les produits avec l'ID de la sous-catégorie et l'ajoute à la liste Produkty. La structure de la base de données est plutôt méchante, car la liste des catégories est téléchargée à partir d'un autre serveur de service de la boutique et il fallait obtenir notre propre colonne d'ID au cas où le serveur étranger changerait la structure.

Il ya plus de 30 000 entrées dans la liste des catégories, certaines d'entre elles auront 5 parents ou plus, et le site affichera uniquement les catégories et sous-catégories principales (les sous-catégories "inférieures" sont requises par un magasin externe connecté avec SOAP) .

Ma question est

Est-ce que l'ajout table d'index à la base de données (catégorie 123 est parent pour 1234, 12738 ...) permettra d'améliorer la performance, ou est-ce juste perte de temps? (L'index devrait être mis à jour lorsque la version de l'API change et je n'ai aucune idée de la fréquence à laquelle cela se produirait) Ou y a-t-il un autre moyen de le faire?

Je demande parce que la modification du script ne sera pas possible en production, et je ne sais pas comment le moteur db gère beaucoup de demandes - j'apprécierais vraiment toute aide avec ceci.

La base de données est MSSQL


* Code Trop; n'a pas lu

Répondre

1

Le grand gain d'efficacité que vous pouvez obtenir est de charger tous les sous-produits dans une seule requête. Le temps économisé en réduisant les voyages en réseau peut être énorme. Si 1 est une catégorie racine et 12 une catégorie enfant, vous pouvez interroger toutes les catégories de racines et de leurs enfants comme:

select * 
from Categories 
where len(Category) <= 2 

Un index Catégorie ne contribuerait pas à la requête ci-dessus. Mais c'est une bonne pratique d'avoir une clé primaire sur n'importe quelle table. Donc, je ferais de la catégorie la clé primaire. Une clé primaire est unique, évite les doublons et est indexée automatiquement.

S'éloigner de RBAR (ligne par ligne agonisante) a plus d'effet qu'un réglage correct de la base de données. Donc je m'attaquerais à ça en premier.

+0

Je connais un peu le SQL et je ne savais pas que c'était possible - merci pour cela . Sera-t-il possible (et/ou utile) de mettre une telle fonction dans les 'méthodes de base de données' pour l'utiliser plus tard? Et oui, j'ai la clé primaire avec 'AUTO_INCREMENT' dans chaque table, parfois je suis même en colère pourquoi ma base de données ne peut pas le créer automatiquement lors de la création de tables;) – Lemurr

1

Vous devriez définitivement déplacer la récursivité dans la base de données. Cela peut être fait en utilisant l'instruction WITH et Common Table Expressions. Créez ensuite une vue ou une procédure stockée et mappez-la à votre application. Avec cela, vous devriez être capable de réduire les requêtes SQL à deux (ou même un).

+0

Merci pour la réponse - Je pense que je dois enfin apprendre le SQL juste pour savoir ce qu'il est possible de faire là ... – Lemurr

Questions connexes