2010-02-11 6 views
4

Ceci est, espérons juste une simple question impliquant l'optimisation des performances en matière de requêtes en Sql 2008.Sql Optimisation: Xml ou Délimité chaîne

J'ai travaillé pour les entreprises qui utilisent stockées procs beaucoup pour leurs processus ETL comme ainsi que certains de leurs sites Web. J'ai vu le scénario où ils ont besoin de récupérer des enregistrements spécifiques en fonction d'un ensemble fini de valeurs clés. Je l'ai vu manipulé de 3 manières différentes, illustré par pseudo-code ci-dessous.

Sql dynamique qui concatène une chaîne et l'exécute.

EXEC('SELECT * FROM TableX WHERE xId IN (' + @Parameter + ')' 

Utilisation d'une fonction définie par l'utilisateur pour diviser une chaîne délimitée dans une table

SELECT * FROM TableY INNER JOIN SPLIT(@Parameter) ON yID = splitId 

XML en utilisant comme paramètre au lieu d'une valeur de varchar délimitée

SELECT * FROM TableZ JOIN @Parameter.Nodes(xpath) AS x (y) ON ... 

Même si je sais que la création du SQL dynamique dans le premier extrait est une mauvaise idée Pour un grand nombre de raisons, ma curiosité vient des deux derniers exemples. Est-il plus efficace de faire preuve de diligence raisonnable dans mon code pour transmettre ces listes via XML comme dans l'extrait 3 ou est-il préférable de simplement délimiter les valeurs et d'utiliser un fichier udf pour s'en occuper?

Répondre

5

Il existe maintenant une 4ème option - table valued parameters, dans laquelle vous pouvez réellement passer une table de valeurs dans un sproc en tant que paramètre, puis l'utiliser comme une variable de table. Je préférerais cette approche à l'approche XML (ou à l'approche d'analyse CSV)

Je ne peux pas citer des chiffres de performance entre toutes les différentes approches, mais c'est une que j'essayerais - je recommanderais de faire de vraies performances tests sur eux.

Editer:
Un peu plus sur les TVP. Pour passer les valeurs à votre sproc, vous devez simplement définir un SqlParameter (SqlDbType.Structured) - la valeur de ceci peut être définie sur n'importe quelle source IEnumerable, DataTable ou DbDataReader. Donc probablement, vous avez déjà la liste des valeurs dans une liste/tableau de quelque sorte - vous n'avez pas besoin de faire quoi que ce soit pour le transformer en XML ou CSV.

Je pense que cela rend également le sproc plus clair, plus simple et plus facile à entretenir, fournissant une manière plus naturelle d'atteindre le résultat final. L'un des points principaux est que le SQL est le plus performant dans les activités basées sur des ensembles/non en boucle/non liées à des chaînes. Cela ne veut pas dire qu'il fonctionnera bien avec un grand nombre de valeurs transmises. Mais avec des ensembles plus petits (jusqu'à ~ 1000) ça devrait aller.

+0

+1. Belle prise. – Quassnoi

+0

Cela ne suffirait-il pas, assez souvent, à pousser le besoin d'analyser-n-charger les données en format tabulaire en amont de l'application? À quel point, qu'est-ce qui est le plus rapide ici - XML ​​ou analyse de code en boucle? –

+0

+1 Excellente explication sur l'utilisation des paramètres de table du côté du code au-delà de DataReaders et DataTables. – JamesEggers

2

UDF invocation est un peu plus coûteux que de diviser le XML en utilisant la fonction intégrée. Cependant, ceci ne doit être fait qu'une seule fois par requête, donc la différence de performance sera négligeable.

+0

Vrai pour les petits ensembles. Qu'en est-il des grands, pour différentes valeurs de "gros"? –

+3

@Philip: C'est encore plus vrai pour les grands ensembles. 'TSQL' manque de pointeurs, donc pour analyser les longues cordes, il appellera notre bon vieil ami Schlemiel le peintre. L'analyse 'XML' est faite en interne et optimisée assez bien. – Quassnoi