Question

Je souhaite utiliser les tables de la meilleure manière possible.
J'ai une table IpToCountry et j'en crée une nouvelle chaque semaine en fonction d'un fichier CSV externe que j'importe.

Le moyen le plus rapide que j'ai trouvé pour effectuer le basculement était le suivant:

sp_rename IpToCountry IpToCountryOld
go
sp_rename IpToCountryNew IpToCountry
go

Le problème, c'est que la table peut toujours être consultée entre les deux.
Comment aborder ce problème en SQL?
Envisager d'utiliser sp_getapplock et sp_releaseapplock, mais je souhaite que la fonction de lecture de la table soit aussi rapide que possible.

Était-ce utile?

La solution

En supposant que vous ne parvenez pas à mettre à jour / insérer dans la table existante, pourquoi ne pas envelopper tous les accès à la table à l'aide d'un view ?

Par exemple, vous pourriez initialement stocker vos données dans une table appelée IpToCountry20090303 , et votre vue ressemblerait à ceci:

CREATE VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090303

Lorsque les nouvelles données arrivent, vous pouvez créer et renseigner la table IpToCountry20090310 . Une fois le tableau rempli, il vous suffit de mettre à jour votre vue:

ALTER VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090310

Le commutateur sera complètement atomique, sans nécessiter de verrouillage ou de transaction explicite. Une fois la vue mise à jour, vous pouvez simplement supprimer l’ancienne table (ou la conserver si vous préférez).

Autres conseils

Une autre méthode permettant de mettre en oeuvre vos objectifs consiste à utiliser le partitionnement de table, technique disponible dans l'édition Enterprise de SQL Server.

Le nom de la table peut rester le même. Une fois l’importation de votre table terminée, il vous suffit de changer la partition contenant vos anciennes données et de basculer dans la nouvelle partition.

Le livre blanc suivant contient toutes les informations nécessaires pour commencer.

http://msdn.microsoft.com/en-us/library /ms345146.aspx

À la vôtre John

J'ai eu du mal à faire fonctionner les fonctions de partitionnement à grande échelle. CREATE et DROP PARTITION sont des opérations de blocage et vous avez peu de contrôle sur le blocage. S'il ne parvient pas à obtenir un verrou, il échouera avec un niveau de gravité 16 et supprimera votre connexion, ce que vous ne pourrez ni intercepter ni réessayer sans rétablir. la connexion. Mais cela pourrait bien fonctionner pour vous. De plus, MSS Enterprise Edition est requis, vous ne pouvez pas utiliser SE - peut-être trop pour certains magasins plus petits ou plus soucieux des coûts.

J'ai également trouvé la vue redef à bloquer à grande échelle (= volume de transactions + volume considérable de données constamment insérées, dans mon cas) sur des tables et des objets système, afin que ces opérations puissent aboutir à des blocages tels que la réindexation et la réindexation. DTCC - et dans un cas, en particulier avec un utilisateur de SSMS (parmi toutes choses) essayant de parcourir les vues dans l'explorateur d'objets (quelqu'un doit leur parler de READPAST). Encore une fois, votre kilométrage peut varier.

En revanche, sp_rename me convient bien à l’échelle: il vous permet de contrôler le verrouillage et son étendue. Pour résoudre le problème de blocage avant l'échange, essayez-le comme indiqué ci-dessous. À première vue, cela semblerait avoir le même problème d'échelle à volume élevé ... mais je ne l'ai pas vu dans la pratique. Alors, ça marche pour moi ... mais encore une fois, les besoins et les expériences de chacun sont différents.

DECLARE @dummylock bit 
BEGIN TRANSACTION 
BEGIN TRY
   -- necessary to obtain exclusive lock on the table prior to swapping
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM A WITH (TABLOCKX))
   -- may or may not be necessary in your case
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM B WITH (TABLOCKX))
   exec sp_rename 'A', 'TEMP'
   exec sp_rename 'B', 'A'
   exec sp_rename 'TEMP', 'B'
   COMMIT TRANSACTION
END TRY
BEGIN CATCH
   -- other error handling here if needed
   ROLLBACK TRANSACTION 
END CATCH

Qu'advient-il d'IpToCountryOld? Est-ce que vous le jetez? Dans ce cas, pourquoi ne pas tronquer IpToCountry et importer mes nouvelles données.

Si vous devez conserver les données, pourquoi ne pas stocker la date de chargement sur la table et stocker les " actualités " date de chargement quelque part à utiliser dans une clause WHERE? Ensuite, vous changez la date du moment où les données sont chargées avec succès.

Vous ne dites pas quelle base de données vous utilisez, je ne sais donc pas à quoi elle sert, mais avez-vous des procédures stockées qui font référence à la table? Sachez que sur certaines plates-formes, les SP sont compilés à l'aide de références internes à des tables qui ne changeront pas si elles sont renommées. Il existe donc un risque que les SP ne récupèrent pas vos nouvelles données sans une recompilation. Il en va de même pour les vues et les requêtes analysées stockées.

Ne pouvez-vous pas importer dans la seule table pendant les heures creuses?

Ou pourquoi ne pas simplement mettre à jour les données, c'est-à-dire mettre à jour les enregistrements existants et en ajouter de nouveaux, enregistrement par enregistrement, au fur et à mesure que vous effectuez une boucle pour importer les données. Cela permettrait à la table de rester active et réduirait l'impact global de l'ajout et de la suppression de tables complètes.

Quelle est la structure des données importées, la conception des tableaux, le format, la PK, etc.? À partir de là, nous pourrons peut-être mieux vous répondre.

Je viens de rencontrer un problème similaire lié à la mise à l'échelle des verrous appropriés sur une table intermédiaire.

Partout où votre table est référencée, vous pouvez appeler une procédure stockée demandant le nom de la table.

La procédure stockée créerait éventuellement la ou les nouvelles tables ou renverrait les anciennes tables en fonction des paramètres fournis.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top