2016-05-20 1 views
0

J'ai la procédure stockée suivante pour parcourir des centaines de fichiers JSON différents qui sont téléchargés sur le serveur tous les jours. Le problème est que la requête prend un bon 15 minutes à courir, je vais devoir créer quelque chose de similaire bientôt pour un plus grand nombre de fichiers JSON, est-ce que quelqu'un est capable de me diriger dans la bonne direction en ce qui concerne l'augmentation des performances de la requête?Performances Openrowset de SQL Server

DECLARE @json VARCHAR(MAX) = '' 
DECLARE @Int INT = 1 
DECLARE @Union INT = 0 
DECLARE @sql NVARCHAR(max) 
DECLARE @PageNo INT = 300 

WHILE (@Int < @PageNo) 
BEGIN 
    SET @sql = (
    'SELECT 
     @cnt = value 
    FROM 
     OPENROWSET (BULK ''C:\JSON\tickets' + CONVERT(varchar(10), @Int) + '.json'', SINGLE_CLOB) as j 
     CROSS APPLY OPENJSON(BulkColumn) 
    WHERE 
     [key] = ''tickets'' 
    ') 
EXECUTE sp_executesql @sql, N'@cnt nvarchar(max) OUTPUT', @[email protected] OUTPUT 

IF NOT EXISTS (SELECT * FROM OPENJSON(@json) WITH ([id] int) j JOIN tickets t on t.id = j.id) 
BEGIN 
    INSERT INTO 
     tickets (id, Field1) 
    SELECT 
     * 
    FROM OPENJSON(@json) 
     WITH ([id] int, Field1 int) 
END 

END 

Répondre

0

Il semble que votre BULK INSERT dans la boucle soit le goulot d'étranglement. Généralement, un INSULME EN VRAC est le moyen le plus rapide de récupérer des données. Quoi qu'il en soit, ici, il semble que le nombre de fichiers est votre problème.

Pour accélérer les choses, vous devriez lire les fichiers JSON en parallèle. Vous pouvez le faire en créant d'abord la requête SQL dynamique complète pour tous les fichiers ou peut-être pour certains groupes de fichiers et en même temps lire.

Je conseille plutôt d'utiliser Integration Services avec un composant de script comme source dans les tâches de flux de données parallèles. Lisez d'abord tous les fichiers de votre dossier de destination, divisez-les par exemple en 4 groupes, car chaque groupe dispose d'un conteneur de boucles qui s'exécute en parallèle. En fonction de votre machine en cours d'exécution, vous pouvez utiliser autant de flux parallèles que possible. Déjà 2 flux de données doivent compenser les frais généraux des services d'intégration.

Une autre option serait d'écrire un CLR (common language runtime) stored procedure et de désérialiser parallèlement JSON en utilisant C#.

Cela dépend également de la machine qui fait le travail. Vous voudriez avoir assez de mémoire à accès aléatoire et de puissance de processeur libre, ainsi il devrait être considéré pour faire l'importation pendant que la machine n'est pas occupée.

0

Une méthode avec laquelle j'ai réussi à charger des données dans des tables à partir de nombreux fichiers XML individuels, que vous pouvez appliquer à ce problème, consiste à utiliser la fonction FileTable du serveur SQL.

La manière dont cela fonctionnait consistait à configurer un fichier dans la base de données, puis à autoriser l'accès au partage FileStream créé sur le serveur pour le processus de téléchargement des fichiers XML. Les fichiers XML ont ensuite été déposés dans le partage et immédiatement disponibles dans la base de données pour l'interrogation à l'aide de xPath. Un processus exécuterait alors les requêtes xPath chargerait les données requises du XML dans les tables requises et garderait la trace des fichiers qui avaient été chargés, puis, lors de la prochaine programmation, ne chargerait que les données des fichiers les plus récents.

Une tâche planifiée sur la machine supprimerait alors les fichiers lorsqu'ils n'étaient plus nécessaires.

avoir une lecture sur FileTable ici:

FileTables (SQL Server)

Il est disponible dans toutes les éditions du serveur SQL.