2010-08-09 3 views
3

Excuses pour la longueur de cette question.Recommandations pour la meilleure mise à jour SQL Performance et/ou le calcul des totaux stockonhand

J'ai une section de notre conception de base de données qui m'inquiète peut commencer à causer des problèmes. Ce n'est pas encore à ce stade, mais évidemment, je ne veux pas attendre jusqu'à ce que ce soit pour résoudre le problème. Mais avant que je commence à tester divers scénarios, j'apprécierais la contribution de toute personne ayant de l'expérience avec un tel problème.

La situation est Stock Control et maintien de la valeur StockOnHand.

Il serait possible de maintenir une table contenant les chiffres de contrôle de stock qui peuvent être mis à jour chaque fois qu'un ordre est entré manuellement ou en utilisant un déclencheur de base de données. Alternativement, vous pouvez obtenir SQL pour calculer les quantités en lisant et en additionnant les valeurs de ventes réelles.

Le programme est installé sur plusieurs sites dont certains utilisent MS-SQL 2005 et certains 2008.

Mon problème est compliqué parce que la même conception doit faire face à plusieurs scénarios, tels que:

1) Environnement de vente au comptant/de vente. La vente est entrée et le stock est réduit en une seule transaction. Aucune modification ne peut être faite à cette transaction.

2) Ordre/Routage/Confirmation Dans cet environnement, la commande est créée et peut être mise en attente, validée, acheminée, modifiée, livrée et facturée. Et à tout moment jusqu'à ce qu'il soit facturé, l'ordre peut être modifié. (Je mentionne cela parce que tous les déclencheurs de base de données peuvent être invoqués beaucoup de temps et doivent déterminer si les changements devraient affecter les stocks sur les chiffres)

3) Les entreprises différentes ont une idée différente de quand leur StockOnHand devrait être réduit. Par exemple, certains considèrent que les actions sont vendues lorsqu'elles approuvent une commande (puisqu'elles se sont engagées à vendre les marchandises et, partant, qu'elles ne devraient pas être vendues à une autre personne). D'autres ne considèrent pas le stock comme étant vendu tant qu'il ne l'a pas acheminé et d'autres seulement lorsqu'il a été livré ou collecté.

4) Il peut y avoir une grande variance dans le nombre de transactions par produit. Par exemple, un système a quatre ou cinq produits qui sont vendus plusieurs milliers de fois par mois, alors demander à SQL d'effectuer une somme sur ces transactions lit dix des milliers de transactions par an, alors que, sur le même système, il y en a plusieurs milliers d'autres produits où les ventes ne seraient que de moins de mille transactions par an et par produit.

5) L'information historique est importante. Pour cette raison, notre système ne supprime ni n'archive les transactions et a plusieurs années de transactions. 6) Le système doit avoir la capacité d'avertir les opérateurs s'ils n'ont pas le stock requis lors de la saisie de la commande (ce qui est souvent le cas en temps réel, par exemple commande téléphonique). Notez que ceci n'est requis que pour certains produits. (Mais je ne pense pas qu'il serait pratique d'additionner la quantité de transactions sur dix ou milliers de transactions en temps réel).

7) Prix moyen des coûts. Certains produits peuvent être évalués en fonction du coût moyen des articles en stock. La façon dont cela est mis en œuvre est que le prix du coût moyen est recalculé pour chaque marchandise dans la transaction, quelque chose comme newAverageCostPrice = (((oldAverageCostPrice * oldStockOnHand) + newCostValue)/newStockOnHand). Cela signifie que le stock en main doit être connu pour chaque marchandise si le produit utilise AverageCost.

La façon dont le système est actuellement implémenté est double. Nous avons une table qui contient le StockOnHand pour chaque produit et emplacement. Chaque fois qu'une vente est mise à jour, cette table est mise à jour via la couche de gestion de notre application (C#) Ceci ne fournit que le stock actuel en main.

Si vous devez exécuter une valorisation de stock pour une date donnée, ce chiffre est calculé en effectuant une somme des quantités sur les lignes concernées. Cela nécessite également une jointure entre la ligne de vente et les tables d'en-tête de vente car la quantité et le produit sont stockés dans le fichier de ligne et la date et le statut sont uniquement conservés dans la table d'en-tête.

Cependant, il existe des inconvénients à cette méthode, tels que.

L'exécution du rapport d'évaluation des stocks est lente (mais pas d'une lenteur inacceptable), mais je ne suis pas satisfait. (Cela fonctionne et surveiller le serveur ne le montre pas surchargé, mais il a le potentiel de causer des problèmes et donc nécessite une surveillance régulière)

La logique du code mettant à jour la table StockOnHand est compliquée.

Cette table est mise à jour fréquemment. Dans de nombreux cas, cela n'est pas nécessaire car les informations n'ont pas besoin d'être vérifiées. Par exemple, si 90% de votre entreprise vend 4 ou 5 produits, vous n'avez pas besoin d'un ordinateur pour vous dire que vous êtes en rupture de stock.

Base de données de triggers. Je n'ai jamais implémenté de déclencheurs compliqués auparavant, alors méfiez-vous de cela. Par exemple, comme indiqué précédemment, nous avons besoin d'options de configuration pour déterminer les conditions dans lesquelles les chiffres de stock doivent être mis à jour. Ceci est actuellement lu une fois et mis en cache dans notre programme. Faire cela à l'intérieur d'un déclencheur signifierait nécessairement lire cette information pour chaque déclencheur. Est-ce que cela a un grand impact sur la performance.

Nous pouvons également avoir besoin d'un déclencheur sur l'en-tête de vente et la ligne de vente. (Cela pourrait signifier qu'une modification de l'en-tête de vente serait obligée de lire les lignes et de mettre à jour le stock pour les produits concernés, puis plus tard les lignes seraient sauvegardées et un autre déclencheur de base de données modifierait à nouveau la Une autre alternative serait de ne mettre à jour la table StockOnHand que lorsque la transaction est facturée (ce qui signifie qu'aucune autre modification ne peut être effectuée) et de fournir une fonction pour calculer le chiffre stockonhand basé sur une union de cette table et les transactions non facturées qui affectent stock.

Tout conseil serait

+0

Pouvez-vous ajouter un 'tldr;'? – RedFilter

+0

Avez-vous envisagé d'avoir une base de données de type entrepôt de dates à des fins de reporting? Cette somme peut être effectuée toutes les deux heures pour votre mise à jour de la base de données de reporting. – Paddy

+0

L'a considéré, mais l'a écarté pour un certain nombre de raisons. Il semble commun d'effectuer l'évaluation des stocks, puis de procéder à des corrections (par exemple pour le gaspillage) et de réexécuter l'évaluation des stocks.Je pense que cela causerait plus de problèmes si les chiffres des stocks n'incluaient pas ces corrections. – sgmoore

Répondre

0

grandement appréciée. Pouvez-vous créer un vi ew (ou vues) pour représenter votre stock? Cela prendrait la responsabilité de faire les calculs sur des déclencheurs synchrones qui ralentissent vos transactions. L'utilisation de plusieurs vues pourrait satisfaire à l'exigence "Différentes entreprises ont des idées différentes de quand leur StockOnHand devrait être réduit." En supposant que vous pouvez répondre aux exigences strictes, creating an indexed view pourrait encore améliorer vos performances.

+0

Cela ne me dérange pas l'idée d'avoir plusieurs vues non indexées en fonction des besoins de l'entreprise, mais alors une vue non indexée serait-elle différente d'une requête équivalente? Je n'aime pas l'idée d'avoir plusieurs vues indexées car je suppose que cela aurait un impact sur le serveur. Je préférerais ne pas avoir une vue indexée et donc besoin de personnaliser la vue par base de données, mais c'est peut-être quelque chose qui doit être fait. – sgmoore

0

Juste quelques idées du haut de ma tête:

au lieu d'un déclencheur (et les données de SOH persistants), vous pouvez utiliser une colonne calculée (par exemple SOH par produit et par magasin). Toutefois, l'impact sur les performances de l'évaluation de ce serait probablement abyssal, sauf s'il y a plus d'écritures dans vos tables sources que de lectures dans votre colonne calculée. (Le compromis est que cela suppose que la seule raison pour laquelle vous calculez le SOH est que vous puissiez le relire.Si vous mettez à jour les données sources du calcul beaucoup plus souvent que vous n'en avez réellement besoin, alors la colonne calculée peut avoir un sens - car il s'agit d'une évaluation JIT uniquement si nécessaire. Ce serait inhabituel cependant - les lectures sont généralement plus fréquentes que les écritures dans la plupart des systèmes)

Je suppose que la raison pour laquelle vous regardez les déclencheurs est parce que les tables source pour les figures SOH sont mises à jour à partir d'un grand nombre de procs/code pour éviter la surveillance (par opposition à un rappel d'un SPROC recalc à partir de tous les points applicables où les données source ont été modifiées?)

Un positionnement IMHO compliqué dans les déclencheurs DB n'est pas conseillé, car cela affecterait négativement les performances. des insertions/mises à jour de volume élevé, et les déclencheurs ne sont pas grands pour la maintenabilité.

Le calcul SOH doit-il être en temps réel? Sinon, vous pouvez implémenter un mécanisme pour mettre en file d'attente les demandes de recalcul (par exemple en utilisant un déclencheur pour indiquer que la balance produit/emplacement est sale), puis exécuter un service de recalcul toutes les quelques minutes en temps quasi réel. Les calculs critiques de la mission (par exemple financiers - comme votre # 6) peuvent néanmoins détecter qu'un chiffrement SOH est sale et forcer un recalc avant de faire une transaction.

Re: 3 - Ouch. Je recommanderais que vous vous entendiez sur un ensemble cohérent de termes (stock en stock, stock engagé, stock en transit, rétrécissement, etc), puis essayez de convaincre vos clients de se conformer à une norme. Mais c'est dans le monde idéal bien sûr!

+0

Merci pour la réponse. Vous ne savez pas comment une colonne calculée peut vous aider. Si cela a été calculé en additionnant les quantités sur les lignes, je ne pense pas que la performance soit suffisante. Re déclencheurs, je me méfiais de les utiliser dans cette situation, mais les «regardait» parce que je ne voulais rien exclure. Je suppose que je cherchais à voir si j'aurais un oui ou un non à cette idée. Le calcul SOH doit être en temps réel dans certains cas, mais le drapeau sale peut être utile. Re 3, Malheureusement, nous ne pouvons pas vraiment forcer nos clients à travailler d'une manière particulière. – sgmoore

1

d'abord je vous recommande fortement d'ajouter « StockOnHand », « ReservedStock » et « SoldStock » à votre table.

Une vente au comptant serait immédiatement soustraire la vente de "StockOnHand" et l'ajouter à "SoldStock", pour une commande vous laisserait "StockOnHand" seul et ajouter simplement la vente à ReservedStock, quand le stock est finalement facturé, vous soustrayez la vente de StockOnHand et Stock réservé et l'ajouter à "SoldStock".

Les utilisateurs professionnels peuvent alors choisir entre StockOnHand ou StockOnHand - ReservedStock. L'utilisation d'une figure de StockOnHand maintiendra une réduction massive des temps d'interrogation, contre le faible risque que la figure puisse devenir incohérente si vous dérangez la logique de votre programme.

Si vos clients sont tellement la chance d'expérimenter la mise à jour contention lors du maintien de la figure StockOnHand (c.-à-sont-ils susceptibles de traiter plus de cinq ventes par seconde aux heures de pointe), vous pouvez consisider le schéma suivant: -

Calculer le chiffre de StockOnHand en comptant les livraisons - ventes ou autres. Lorsqu'une vente est confirmée, insérez une ligne dans un tableau "Ventes d'aujourd'hui". Lorsque vous avez besoin d'interroger le stock disponible jusqu'à aujourd'hui, soustrayez-le du chiffre du début de la journée. Vous pouvez également placer un "Stock Check Threshold" sur chaque produit, donc si vous commencez la journée avec 10 000 widgets, vous pouvez définir CheckThreshold à 100 si quelqu'un commande moins de 100 que de ne pas prendre la peine de vérifier le stock. Si quelqu'un commande plus de 100, vérifiez le stock et recalculez un nouveau seuil inférieur.

Questions connexes