À l'aide d'une table de base de données comme une file d'attente
Je veux utiliser une table de base de données comme une file d'attente. Je veux insérer en elle et de prendre des éléments dans l'ordre inséré (FIFO). Mon compte principal est la performance parce que j'ai des milliers de ces opérations à la seconde. Donc, je veux utiliser une requête SQL qui me donne le premier élément sans chercher l'ensemble de la table. Je n'ai pas supprimer une ligne quand je l'ai lu.
Ne SÉLECTIONNEZ HAUT 1 ..... de l'aide ici?
Dois-je utiliser une spéciale index?
- Voir cet article pour une bonne description de la manière d'implémenter une file d'attente dans SQL Server: mssqltips.com/sqlservertip/1257/...
- à l'aide de ligne de base de la logique tels que le traitement de la file d'attente dans sql server est un énorme détournement de ressources.. l'utilisation de sql pour la logique
Vous devez vous connecter pour publier un commentaire.
Je voudrais utiliser une IDENTITÉ champ comme clé primaire pour fournir l'unique et l'incrémentation de l'ID pour chaque élément de file d'attente, et le bâton d'un index cluster. Cela représenterait de l'ordre dans lequel les éléments ont été mis en file d'attente.
À conserver les éléments dans la file d'attente de table tout en vous traiter, vous auriez besoin d'un champ "statut" pour indiquer l'état actuel d'un élément particulier (par exemple, 0=en attente, 1=en cours de traitement, 2=traitées). Cela est nécessaire pour prévenir un élément de traiter deux fois.
Lors du traitement d'éléments dans la file d'attente, vous auriez besoin de trouver l'élément suivant dans la table PAS actuellement en cours de traitement. Cela aurait besoin d'être dans une telle façon afin d'éviter que plusieurs des processus de la cueillette jusqu'à la même élément de processus en même temps que démontré ci-dessous. Remarque le les indicateurs de table UPDLOCK et READPAST laquelle vous devez être au courant lors de la mise en œuvre des files d'attente.
par exemple à l'intérieur d'une procédure stockée, quelque chose comme ceci:
Si le traitement d'un élément échoue, vous voulez être en mesure d'essayer de nouveau plus tard? Si oui, vous aurez besoin de réinitialiser le statut de nouveau à 0 ou quelque chose. Qui demanderont plus de réflexion.
Alternativement, ne pas utiliser une table de base de données comme une file d'attente, mais quelque chose comme MSMQ - juste pensé que je jetterais que dans le mix!
Si vous ne retirez pas votre traitées lignes, alors vous allez avoir besoin d'une sorte de drapeau qui indique qu'une ligne a déjà été traité.
Mettre un index sur le drapeau, et sur la colonne que vous allez à l'ordre par.
Partition de votre table sur le drapeau, de sorte que le dequeued les transactions ne sont pas encombrer vos requêtes.
Si vous voulez vraiment obtenir
1.000
messages à chaque seconde, il en résulterait86.400.000
lignes un jour. Vous pouvez penser d'une certaine manière de nettoyer les vieilles lignes.flag
je veux dire un certain colonne rappelez-vous, si une ligne a déjà été traité par votre client.Tout dépend de votre moteur de base de données/mise en œuvre.
Pour moi simple, les files d'attente sur les tables avec des colonnes suivantes:
travaille habituellement.
J'ai utilisé de la priorité et de la tâche de groupe de tâches et en cas de doublé tâche j'ai choisi celui avec la plus grande priorité.
Et ne vous inquiétez pas - pour des bases de données modernes "des milliers" n'est rien de spécial.
Ce ne sera pas un problème aussi longtemps que vous utilisez quelque chose pour garder une trace de la date de l'insertion. Voir ici pour la mysql options. La question est de savoir si vous avez uniquement besoin de l'absolu, plus récemment soumis élément ou si vous avez besoin pour effectuer une itération. Si vous avez besoin pour effectuer une itération, puis ce que vous devez faire est de saisir un morceau avec un
ORDER BY
déclaration, en boucle, et souviens de la dernière datetime de sorte que vous pouvez l'utiliser lorsque vous prenez votre segment suivant.peut-être l'ajout d'une LIMITE=1 pour votre instruction select aiderait ... forçant le retour après un seul match...
Puisque vous n'avez pas supprimer les enregistrements de la table, vous devez disposer d'un indice composite sur
(processed, id)
, oùprocessed
est la colonne qui indique si l'enregistrement en cours avaient été traitées.La meilleure chose serait de créer une table partitionnée pour vos dossiers et de faire de la
PROCESSED
champ le partitionnement de la clé. De cette façon, vous pouvez garder trois ou plusieurs indices locaux.Toutefois, si vous avez toujours traiter les dossiers dans
id
ordre, et n'ont que deux états, la mise à jour de l'enregistrement signifierait tout simplement prendre l'enregistrement de la première feuille de l'index et de l'ajoutant à la dernière feuilleActuellement traité enregistrement aurait toujours le moins
id
de tous les enregistrements non traités et le plus grandid
de tous les dossiers traités.@Shayan
: cela va fortement influer sur votre sélectionnez la performance. Et vous avez besoin de verrouiller le champ lors du traitement de toute façon.Créer un index cluster sur une date (ou auto-incrément) de la colonne. Cela permet de garder les lignes de la table à peu près dans l'ordre d'index et de permettre rapide d'accès par index lorsque vous
ORDER BY
la colonne indexée. À l'aide deTOP X
(ouLIMIT X
, selon votre RDMBS) n'aura alors qu'à récupérer les x premiers éléments de l'index.Performance avertissement: vous devez toujours examiner les plans d'exécution des requêtes (sur données réelles) pour vérifier que l'optimiseur de ne pas faire des choses inattendues. Essayez également de comparer vos requêtes (encore une fois sur des données réelles) pour être en mesure de prendre des décisions éclairées.
J'ai eu la même question générale de savoir "comment mettre un tableau dans une file d'attente" et ne pouvait pas trouver la réponse que je voulais n'importe où.
Voici ce que j'ai trouvé pour le Nœud/SQLite/mieux-sqlite3.
Fondamentalement, il suffit de modifier l'intérieur
WHERE
etORDER BY
clauses pour votre cas d'utilisation.Une solution très simple pour ceci afin de ne pas avoir les transactions, les verrous etc consiste à utiliser la variation de mécanismes de suivi (pas de capture de données). Il utilise le contrôle de version pour chaque ajout/mise à jour/supprimer ligne afin que vous puissiez suivre ce que des modifications sont intervenues après une version spécifique.
Donc, vous persistez la dernière version de requête et de nouveaux changements.
Si une requête échoue, vous pouvez toujours revenir en arrière et d'interroger les données à partir de la dernière version.
Aussi, si vous ne voulez pas d'obtenir toutes les modifications avec une requête, vous pouvez obtenir le meilleur ordre n de la dernière version et de stocker la plus grande version que j'avais vous avez eu de la requête à nouveau.
Voir ceci par exemple En utilisant le Suivi des modifications dans SQL Server 2008