Créer une fonction dans la base de données centrale ou répéter dans chaque base de données?

8

Un de mes développeurs a écrit une fonction SQL qui fonctionne comme la fonction VB.Net (LastIndexOf) et souhaite la publier. Ma question est quelle serait la raison de mettre cela dans une base de données centrale par rapport à le mettre dans chaque base de données utilisateur?

Le développeur essayait de le mettre dans le schéma sys sur sa base de données principale afin qu'il n'ait pas à qualifier les appels vers celui-ci à partir des bases de données utilisateur ... soupir

Mais je ne savais pas quelle serait l'excuse valable pour la centraliser (évidemment pas la base de données principale) par rapport à chaque base de données d'utilisateurs?

David George
la source
1
Je pense que l'idée derrière cela peut être quelque chose comme «Que feriez-vous dans le cas d'une correction de bogue hypothétique? Aller à chaque base de données et corriger chaque copie séparément? '
dezso
1
Les frais d'administration ne sont pas pertinents ici car je peux mettre à jour toutes les bases de données aussi facilement qu'une seule base de données
David George
Et votre développeur le sait-il? :) Et probablement il / elle sent qu'il implémente une telle fonctionnalité de base qu'elle doit être au cœur même.
dezso
Oui. C'est ma question, un élément qui pourrait être considéré comme essentiel devrait-il faire partie de la base de données utilisateur ou être partagé entre toutes les bases de données à partir d'une seule base de données commune?
David George
Oui, j'ai essayé de présenter deux arguments plus ou moins valables en faveur de la centralisation. Je pense que cela peut être plutôt une question de politique ou de goût personnel - il ressort clairement du libellé que vous n'aimez pas l'idée.
dezso

Réponses:

12

La façon dont je préfère le faire: mettre la fonction dans une base de données utilitaire et créer un synonyme dans chaque base de données régulière. De cette façon, vous obtenez le meilleur des deux mondes:

  1. il n'y a qu'une seule copie de l'objet à maintenir
  2. le développeur n'a pas à fournir de noms en trois ou quatre parties

par exemple

USE UtilityDB;
GO
CREATE FUNCTION dbo.LastIndexOf(...) ...
GO
USE otherDB;
GO
CREATE SYNONYM dbo.LastIndexOf FOR UtilityDB.dbo.LastIndexOf;
GO

Ceci est particulièrement puissant pour les fonctions CLR, car il y a des frais administratifs supplémentaires pour les modifier / déployer.

Et cela est préférable à l'utilisation de master (et au marquage en tant qu'objet système, ce qui n'est pas garanti d'être transférable). J'aimerais cependant savoir comment votre développeur prévoit de créer sa fonction dans le sysschéma.

Je comprends que la maintenance de plusieurs copies d'une fonction dans 500 bases de données n'est pas vraiment plus difficile que la maintenance d'une seule copie, mais avoir plusieurs copies n'est vraiment un avantage que si vous avez des exceptions (par exemple, le client A veut que sa fonction gère les NULL différemment, ou quelque chose). Dans ce cas, je laisserais le synonyme dans toutes les autres bases de données et n'introduirais une version spéciale de la fonction que dans cette base de données.

(Cela suppose que la fonction ne repose sur aucun accès aux données dans la base de données d'un client, bien sûr - ce qui peut certainement compliquer les choses.)

Aaron Bertrand
la source
5

Je vais devoir être en désaccord avec Aaron (et la réponse acceptée).

L'approche d'Aaron est la façon dont j'aime traiter les "trucs DBA", par exemple les scripts de maintenance. Je ne voudrais jamais faire cela avec une fonction de bibliothèque qui serait appelée par une base de données utilisateur.

Pourquoi? Vous vous dirigerez vers l'équivalent de base de données de DLL Hell .

Versions incompatibles

... Avant Windows 2000, Windows était vulnérable à cela car la table de classe COM était partagée entre tous les utilisateurs et processus. Un seul objet COM, dans une DLL / EXE, peut être déclaré comme ayant un ID de classe COM global spécifique sur un système. Si un programme devait créer une instance de cette classe, il obtenait ce qui était l'implémentation enregistrée de manière centralisée actuelle. Par conséquent, une installation d'un programme qui installe une nouvelle version d'un objet commun peut interrompre par inadvertance d'autres programmes précédemment installés.

Installez .net 4.5 sur un serveur exécutant une application .net 2.0 et que se passe-t-il? Rien, votre application continue d'utiliser le framework 2.0. Mettez à jour votre fonction LastIndexOf sur un serveur hébergeant 3 bases de données d'applications (dans le cadre d'une mise à niveau vers l'une d'entre elles) et que se passe-t-il? Tous les trois utilisent maintenant la dernière version.

L'alternative est l'approche adoptée par SQL # . Celui-ci est installé sur un schéma dans chaque base de données utilisateur, vous pouvez donc mettre à niveau la base de données pour Application-X en toute sécurité sans risquer la stabilité d'Application-Y.

Si vous travaillez dans un environnement de gestion des changements étroitement contrôlé, vous n'aurez pas le choix, vous ne pouvez pas mettre à niveau un composant partagé sans tester tous les consommateurs du composant. Si vous travaillez quelque part un peu plus "rapide et lâche", vous êtes libre de tenter votre chance en cassant quelque chose involontairement avec un correctif / mise à niveau.

Mark Storey-Smith
la source
Permettez-moi de fournir une réfutation, car vous sembliez en vouloir une et maintenant j'ai quelques instants à perdre que je n'avais pas auparavant. :-) (1) J'ai supposé que l'ensemble des bases de données en question étaient toutes liées et ne faisaient pas partie d'applications complètement différentes. (2) Dans ce cas, je ne pense pas qu'il y ait beaucoup de danger pour une fonction appelée LastIndexOfà changer, encore moins d'une manière qui ne casse que certaines applications / bases de données. Je dirais que c'est un plus gros problème pour CLR ou des fonctions vraiment centrales / complexes qui desservent plusieurs applications. (3) Ma préférence actuelle serait de ne pas utiliser du tout une fonction pour des tâches simples.
Aaron Bertrand
1
Accueillez toujours vos pensées bien sûr :)
Mark Storey-Smith
Héy. En tant que créateur de SQL # , j'apprécie la mention positive :-). Cependant, je dois préciser que le principal point de décision pour l'utilisation d'un schéma distinct pour tous les objets SQL # était de créer un espace de noms afin qu'il n'y ait pas de conflits de noms, peu importe où SQL # a été installé. Pourtant, vous soulevez un point qui doit être pris en compte concernant la gestion des versions, selon la façon dont l'application est structurée. Personnellement, j'aime avoir une base de Utilitydonnées pour des trucs de bibliothèque communément appelés, mais cela augmente un peu le risque et nécessite des tests approfondis.
Solomon Rutzky
0

La réponse à cette question dépend de si nous parlons d'objets T-SQL ou d'objets SQLCLR. Il existe différents (et plus) facteurs à prendre en compte lors du traitement des objets SQLCLR.

En termes d'objets T-SQL, les deux réponses apportent ici des points valides. Comme décrit dans la réponse de @ Aaron , la base de données centrale peut être très pratique, et les synonymes peuvent être utilisés pour faciliter le pointage de certaines bases de données vers la ressource partagée et d'autres d'utiliser une ressource locale. Mais le point soulevé dans la réponse de Mark concernant le risque accru en raison de la dépendance plus forte ne peut être ignoré.

Cependant, si vous traitez avec des objets SQLCLR, vous devez d'abord considérer tous les points que j'ai soulevés dans la réponse suivante:

Comment mieux utiliser la fonction CLR du point de vue des performances (répéter à l'intérieur de chaque base de données ou avoir une fonction générale)?

Solomon Rutzky
la source