Interaction avec les données à l'aide de plusieurs bases de données / serveurs


18

Tous les projets que j'ai eu à traiter jusqu'à présent n'ont nécessité qu'une seule base de données sur un seul serveur. Je souhaite en savoir plus sur la façon dont les projets qui doivent évoluer évoluent vers plusieurs bases de données et / ou serveurs pour aider à gérer la charge. Je suis conscient de la haute évolutivité , mais je suis particulièrement intéressé par des exemples de code ou des ressources supplémentaires où je pourrais en savoir plus sur le sujet.

Par exemple:

  • Comment les jointures sont-elles construites entre deux tables sur plusieurs bases de données? (Un exemple de code ici serait utile).
  • Existe-t-il des stratégies spéciales pour suivre quelles tables se trouvent dans quelle base de données?
  • Le code d'application doit-il savoir qu'une ou plusieurs bases de données sont réparties sur plusieurs serveurs? Sinon, à quel niveau les demandes sont-elles filtrées?
  • Quand est-il temps d'aller au-delà d'une configuration à 1 base de données / 1 serveur? Est-il courant de devoir faire cela?

Il est préférable de répondre à cette question sur les administrateurs de base de données . Cependant, il n'y a rien de mal à cela, donc je vais juste vérifier avec les mods DBA. Si cela convient, aimeriez-vous qu'il migre?
Adam Lear

@AnnaLear - Je suppose que cela dépend des réponses. À ce stade, je suis plus intéressé par le côté application du problème, donc pour l'instant, je pense que cela pourrait être mieux ici.
VirtuosiMedia

@AnnaLear ack, d'accord avec l'OP puis s'ils veulent du code spécifique à l'application.
jcolebrand

Réponses:


13

Ok, décomposons-le:

  • Comment les jointures sont-elles construites entre deux tables sur plusieurs bases de données? (Un exemple de code ici serait utile).

C'est assez simple. Les objets SQL ont une convention de dénomination d'une à quatre parties:

Servername.databasename.schemaname.tablename

Si toutes vos tables sont sur le même serveur sur la même base de données, avec le même propriétaire / schéma, vous pouvez simplement ignorer les trois premières parties et utiliser ce à quoi vous êtes le plus habitué:

Select a.*,b.* from 
tableA a inner join 
tableB b on a.col1=b.col1

Si l'une de vos tables se trouve dans une base de données différente et que les deux utilisent le schéma par défaut pour leurs bases de données, vous ajoutez simplement la base de données à la deuxième table:

Select a.*,b.* from 
tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

Si vous vous trouvez dans une troisième base de données différente de l'une de celles que vous interrogez, vous utilisez explicitement les deux noms de base de données:

Select a.*,b.* from 
databaseD..tableA a inner join 
databaseC..tableB b on a.col1 = b.col1

Si vous finissez par utiliser différents schémas et / ou propriétaires, vous pouvez les ajouter dans:

Select a.*,b.* from 
databaseD.john.tableA a inner join 
databaseC.accounting.tableB b on a.col1 = b.col1

Et enfin, si vous y faites très attention et que vous avez une très bonne raison, vous pouvez rejoindre une table (généralement petite) sur un autre serveur:

Select a.* from 
databaseD.john.TableA a inner join 
ATLANTA.databaseC.accounting.tableB b on a.col1 = b.col1
  • Quand est-il temps d'aller au-delà d'une configuration à 1 base de données / 1 serveur? Est-il courant de devoir faire cela? Existe-t-il des stratégies spéciales pour suivre les tables dans quelle base de données?

Je vais combiner ces deux parce qu'ils vont ensemble. Vous êtes presque toujours d'accord pour commencer avec l'hypothèse qu'une base de données, un serveur est suffisant jusqu'à ce que vos contraintes de conception / métier / techniques vous obligent à en utiliser davantage.

Donc, pour répondre à votre deuxième question en premier, puisque vous avez généralement une raison d'avoir des bases de données distinctes, il devrait être assez évident de connaître la conception de votre système où se trouve quelque chose.

Quant à savoir quand / pourquoi il est nécessaire d'aller au-delà d'une seule base de données. Il s'agit généralement d'un mélange de règles commerciales, politiques et / ou techniques.

Par exemple, où je travaille, nous avons 16 bases de données réparties sur 4 serveurs. Nous avons un MainDB, ImageDB, referencetableDB, HighvolumeTransactionDB, ReportingDB, StagingDB, ProcessingDB, ArchiveDB, FinancialDB. Pour donner quelques exemples de leurs différences:

  • FinancialDB, informations sensibles
  • Base de données d'images, différentes exigences spécifiques de stockage et de récupération
  • ReferenceDB, faible transaction, lecture élevée
  • ReportingDB, lecture très élevée, doit être restauré / répliqué dans divers autres environnements contrairement à beaucoup d'autres données
  • StagingDB, rien de permanent, juste un tempdb renforcé sur lequel nous avons plus de contrôle
  • MainDB, s'interface avec toutes les autres bases de données, mais a besoin de sauvegardes différentielles donc ... nous divisons le
  • Tables HighVolumeTransaction, (qui sont relativement transitoires), vers leur propre base de données afin de conserver une taille de sauvegarde raisonnable.
  • Archive, Beaucoup des mêmes données de Main et Reporting, mais avec des périodes de rétention plus longues et des requêtes plus difficiles à creuser profondément dans les données. Si cela était toujours combiné avec Main / Reporting, cela entraînerait un blocage de notre système.

Le code d'application doit-il savoir qu'une ou plusieurs bases de données sont réparties sur plusieurs serveurs? Sinon, à quel niveau les demandes sont-elles filtrées?

Au sens large, ils le font probablement. Ils doivent au minimum savoir sur quel serveur ils pointent dans la chaîne de connexion à la base de données. Traitement, rapport, principal, etc.

À partir de là, ils ont besoin d'un contexte de base de données pour s'exécuter. En général, ce serait le plus utilisé pour l'application, peut-être même l'original de la base de données / un serveur jours de l'application. Vous POUVEZ faire en sorte que l'application change explicitement le contexte de la base de données à chaque appel, mais cela rend très difficile l'ajustement de la base de données sans changer l'application.

L'approche habituelle (ou du moins MON habituelle) consiste à toujours accéder via une ou peut-être deux bases de données principales.

Créez ensuite des vues dans d'autres bases de données si nécessaire, combinées à une interface avec la base de données via des procédures stockées.

Donc pour illustrer:

Supposons que vous souhaitiez obtenir les informations démographiques, les données de vente et le solde créditeur d'un client, et que ces informations soient réparties sur trois tableaux, tous à l'origine dans MainDB.

Vous écrivez donc un appel depuis votre application:

Select c.ClientName, c.ClientAddress, s.totalSales,f.CreditBlance from
Clients c join Sales s on c.clientid = s.clientid inner join AccountReceivable f on 
c.clientid=f.clientid where c.clientid = @clientid

Impressionnant. Cependant, à chaque fois que nous modifions un nom de colonne ou renommons / déplaçons une table, vous devez mettre à jour le code de l'application. Donc, au lieu de cela, nous faisons deux choses:
créer des clients, des ventes, des vues AccountReceivables (vous n'utiliseriez pas Select * mais je fais une démonstration ici)

Use MainDB
GO
Create view v_Clients as select * from Clients
Create view v_Sales as select * from Sales
Create view v_AccountReceivable as select * from AccountReceivable
Go

Ensuite, nous créerions également une procédure stockée, spGetClientSalesAR

Create proc spGetClientSalesAR @clientID int
as
Select c.ClientName as ClientName, 
       c.ClientAddress as ClientAddress, 
       s.totalSales as TotalSales, 
       f.CreditBlance as CreditBalance 
from
v_Clients c join v_Sales s 
    on c.clientid = s.clientid 
inner join v_AccountReceivable f 
    on c.clientid=f.clientid 
where c.clientid = @clientid

Et demandez à votre application d'appeler cela.

Maintenant, tant que je ne change pas l'interface sur ce proc stocké, je peux à peu près faire tout ce que je dois faire à la base de données principale pour augmenter ou réduire.

À l'extrême, je pouvais même créer mon ancien MainDB juste un tas de procédures stockées et de vues shellées de sorte que sous ces vues que nous avons créées, cela ressemblait à ceci:

Create view v_Clients as select * from ServerX.DatabaseY.dbo.Clients
Create view v_Sales as select * from ServerQ.DatabaseP.dbo.Sales
Create view v_AccountReceivable as select * from ServerJ.DatabaseK.dbo.AccountReceivable

Et votre application ne connaîtra jamais la différence (en supposant, entre autres, des canaux rapides et des données bien organisées).

Évidemment, c'est extrême et je mentirais si je disais que tout était planifié de cette façon, mais l'utilisation de procédures / vues stockées même si vous le faites tout en refactorisant vous permettra beaucoup de flexibilité à mesure que votre application se développe à partir de son humble base de données / serveur début.


TetonSig - Merci pour la réponse. Je n'ai pas pu revenir à la question à temps pour vous attribuer l'intégralité de la prime (je voyageais), mais j'ai créé une nouvelle prime pour la question et je pourrai vous l'attribuer dans les 24 heures.
VirtuosiMedia

Ouah merci. Je l'apprécie. C'était très amusant de répondre à la question.
TetonSig

5

La principale façon dont j'ai rencontré plusieurs serveurs de bases de données dans le monde Web (puisque la question est balisée PHP) est les configurations où il y avait une base de données `` maître '' (écriture), puis une ou plusieurs bases de données `` esclaves '' (lecture) répliquées . Les écritures de base de données sont effectuées sur la base de données «principale». Le contenu de cette base de données est répliqué sur les serveurs «esclaves» en temps quasi réel. Les requêtes - en particulier les rapports intensifs - sont ensuite exécutées sur l'une des bases de données «esclaves» pour transférer la charge vers ces serveurs. Gardez à l'esprit que cette configuration particulière est préférable pour les applications qui ont beaucoup de lectures, mais pas beaucoup d'écriture. Ce n'est en aucun cas le seul moyen d'arranger les choses.


3

Comment les jointures sont-elles construites entre deux tables sur plusieurs bases de données? (Un exemple de code ici serait utile).

Ils ne sont pas. Les bases de données NoSQL ne font pas du tout de "jointures", et même si vous le pouviez faire une jointure SQL sur des serveurs SGBDR, vous ne le voudriez pas si vous appréciez les performances (cf. erreurs de l'informatique distribuée ).

Existe-t-il des stratégies spéciales pour suivre quelles tables se trouvent dans quelle base de données?

Dans une base de données relationnelle / SQL, le partitionnement est normalement effectué dans les limites d'un seul serveur / base de données, en utilisant différents fichiers placés sur différents disques. Presque par définition, une solution de mise à l'échelle horizontale signifie que tous bases de données ont toutes les tables et que vous disposez d'une sorte de miroir transactionnelle, de réplication ou de cohérence éventuelle pour vous assurer que toutes les données arrivent là où elles sont censées.

Si vous divisez la base de données logique et pas seulement physique, les mappages définis dans votre DAL ou ORM déclareront quelles tables se trouvent dans quelle base de données.

Les bases de données NoSQL sont un mélange de solutions de partitionnement. Parfois, ce sont les "tables" (ou plus communément, les "collections") qui sont partitionnées. D'autres fois, ce sont les "lignes" (ou "documents"). Dans certains cas, c'est en fait le colonnes , comme dans une base de données orientée colonnes comme HBase. Cela dépend totalement de la technologie que vous utilisez. La seule chose que tous ces éléments ont en commun est que le moteur lui-même garde la trace de tout, donc tout ce que vous avez à faire est de demander un document ou une ligne.

Cela suppose bien sûr que vous utilisez réellement les fonctionnalités de partitionnement et pas seulement la création d'un tas de bases de données différentes. Si vous faites ce dernier, alors vous êtes seul.

Le code d'application doit-il savoir qu'une ou plusieurs bases de données sont réparties sur plusieurs serveurs? Sinon, à quel niveau les demandes sont-elles filtrées?

S'il s'agit de différentes bases de données logiques , oui. S'ils ne sont physiquement distribués alors non - en supposant que votre base de données spécifique prend en charge nativement le partage ou que vous utilisez une solution d'équilibrage de charge (pour les bases de données SQL). En supposant également que toutes vos opérations sont apatrides; si vous voulez une mise à l'échelle horizontale, vous allez devoir abandonner ACID.

Quand est-il temps d'aller au-delà d'une configuration à 1 base de données / 1 serveur? Est-il courant de devoir faire cela?

Il est temps que vous optimisiez tout ce que vous pouvez sur un seul serveur et que vous ne puissiez toujours pas obtenir suffisamment de performances en raison de contraintes sur la charge d'E / S. Si vous devez poser la question, c'est trop tôt.

Notez que les problèmes de performances dans un produit SGBDR décent (Oracle, SQL Server) sont plus fréquemment dus à une mauvaise conception, une mauvaise indexation, de mauvaises requêtes, des conflits de verrouillage, etc. ces produits peuvent évoluer verticalement à un degré ridicule. Encore une fois, vous devriez envisager de "dépasser la configuration d'une base de données / serveur 1" lorsque vous êtes absolument certain que vos problèmes de performances sont dus à des limitations matérielles et pas seulement à une conception / implémentation inférieure à la normale.

Ou, je suppose, une autre raison pour laquelle certaines personnes optent pour des bases de données distribuées est lorsqu'elles ne sont pas prêtes à payer beaucoup (ou pas) d'argent en frais de licence et veulent abandonner SQL comme choix délibéré pour échanger le faible coût contre une complexité accrue des applications. Raison tout à fait valable si vous êtes une startup logicielle mais généralement pas applicable dans le secteur des entreprises.


+1 - Je ne pensais pas vraiment à NoSQL, mais cela est tout de même utile. Merci.
VirtuosiMedia

1

Il existe trois principaux types de configurations de réplication pour les bases de données:

  • Maître d'esclave
  • Master-Master
  • Consensus

Exemple maître-esclave: maître MySQL + esclaves MySQL, MongoDB

Exemple Master-Master: CouchDB, Cassandra, Riak

Exemple de consensus: ScalienDB

... pour n'en nommer que quelques-uns.

Celles-ci ont des caractéristiques différentes. Les configurations maître-esclave permettent aux nœuds esclaves de rattraper le maître à leur vitesse maximale tout en répondant très rapidement aux demandes de lecture, tandis que le serveur maître est responsable de l'intégrité des données. Parce que toutes les écritures vont au maître, il n'y a jamais de conflit de verrouillage car un seul écrivain relativement lent bloque de nombreux lecteurs, mais d'un autre côté, les serveurs esclaves sont finalement cohérents et vous n'obtenez pas les garanties d'isolation de transaction que vous auriez de lire seulement du maître. (lecture supplémentaire; ACID vs BASE, Niveaux d'isolement des transactions, réplication de base de données, MVCC / Isolation: Snapshot, Transactional Replication)

Master-Master autorise toujours les écritures, vous auriez donc plusieurs pouvoirs sur ce qui est vrai. Cela peut ou non être un problème, selon ce que fait votre application, mais si vous écrivez des données conflictuelles, vous pouvez obtenir plusieurs résultats la prochaine fois que vous lirez cette clé / ligne / colonne que vous devrez fusionner avec la logique d'application et sauvegarder dans la base de données. (Lectures complémentaires: Théorème CAP, réplication CouchDB, réplication Riak, hachage cohérent, Bitcask & StormDB, Quorum- w / MongoDB sur la division du réseau, stratégies de résolution de fusion)

Les bases de données consensuelles avec réplication entre les nœuds, telles que Scalien, seraient toujours cohérentes sur les écritures, mais au prix d'échanger plusieurs messages avant d'acquitter l'écriture. Ce n'est pas vraiment un problème si vous avez un Ethernet rapide et que vous n'avez pas besoin d'écrire sur le disque avant ACKing, ce dont vous n'aurez pas besoin si votre minimum de trois serveurs sont sur des racks de serveurs différents avec des alimentations séparées (un meurt; les deux autres vérifient qu'ils ont enregistré sur le disque). (lecture supplémentaire; PAXOS, PAXOS COMMIT, validation en deux phases avec transactions distribuées, validation en trois phases)

Autres lectures diverses: (livre: 'Elements of Distributed Computing', horloges vectorielles, vecteurs de version, vecteurs matriciels, horloges logiques, algorithme de boulangerie, horloges d'arbre d'intervalle, acteurs et programmation et réacteurs réactifs, mémoire transactionnelle logicielle, transacteurs, AKKA, Stact, sophismes de l'informatique distribuée, protocoles de ragots, extensions du protocole de ragots anti-entropie de Cassandra, tables de hachage distribuées, articles sur la fusion de données dans un environnement distribué, architecture ZooKeeper, présentation InfoQ sur "protocole asynchrone", architecture HBase, papier MapReduce, papier Amazon Dynamo qui a démarré tous les trucs NoSQL, la file d'attente, le clustering haute disponibilité rabbitmq)

J'espère avoir donné matière à réflexion :). Vous pouvez également me suivre sur Twitter @henrikfeldt si vous souhaitez également des tweets sur ce sujet.


1

OK, voici donc un autre point de vue sur l'évolutivité.

Voyons ce que cela signifie pour les choses d'être des données, ce que cela signifie d'avoir un comportement et ce que cela signifie d'avoir une logique d'application.

Normalement, lorsque l'on s'aventure dans le domaine des applications d'entreprise et autres, on serait exposé à l'idée de superposition. Bien sûr, la superposition est partout dans les ordinateurs, comme dans la pile de mise en réseau (modèle ISO), ou dans les graphiques (Photoshop), ou dans SOA (les services peuvent appeler des frères et sœurs ou des enfants, mais jamais des parents).

Cependant, le type spécifique de couches qui a été abusé sans égard à ce qui est jamais celui de la «GUI», «Business Logic Layer» puis «Data Access Layer». Je veux dire, oui, l'idée est bonne en principe, comme le communisme est bon en principe, mais en réalité ce n'est pas le cas.

Voyons pourquoi. L'argument que je vais utiliser concerne le couplage; les points d'un calque qui touchent les points d'un autre calque. Chaque fois que vous commencez à créer une application en couches alias à n niveaux dans le mode d'entreprise par défaut dans lequel les gens vont, ils créent tellement de points de contact entre les couches.

En son cœur, l'idée est que les couches sont interchangeables; mais ils ne le sont pas! Pourquoi? En raison de tout le couplage site-appel.

Regardez plutôt pourquoi le réseau est découplé! Parce que l'interface est un flux d'octets sur un pointeur de fichier unique qui pointe vers un socket ouvert! Toutes les couches des modèles ISO sont comme ce que le modèle de conception appelé «chaîne de responsabilité» est pour orienter l'objet! Chaque couche enveloppe la couche sous-jacente, sans connaître la sémantique des données de cette couche sous-jacente.

Alors qu'un paquet de données se dirige vers Ethernet et des signaux électriques bruts en bas, il est continuellement enveloppé par des couches qui ne connaissent que sa propre enveloppe de message spécifique, son propre «lot d'octets» qu'il peut envoyer; et rien d'autre. Il n'a pas besoin de modifier les chemins d'appels en fonction du contenu du package.

Comparez cela à n-tier où vous devrez modifier le chemin d'appel dans vos couches d'application sur un `` appel '' traversant vos couches sur son chemin vers la base de données - par exemple, les `` clients or '' sont polymorphiquement un surensemble de `` clients normaux '' et donc parce que nous utilisons «table par sous-classe», nous devons savoir à ce sujet maintenant que les données (entité) traversent les couches; à la fois dans la soi-disant «couche de logique métier» et dans la couche de données qui effectue réellement la sauvegarde.

Ce n'est ni évolutif ni optimal d'un point de vue informatique.

Pourquoi n'est-il pas évolutif? Parce que l'architecture est couplée, et que vous êtes toujours dans la même vieille base de données que vous essayiez d'évoluer vers de nombreux nœuds! Mais, parce que vous avez besoin d'ACID pour cela, cela et une troisième entité (objet de données), vous devez les avoir dans une seule base de données qui effectue des transactions!

Oui, donc avec cette diatribe à l'écart; quelles sont les autres façons?

Eh bien, il y a l'acronyme détesté appelé «SOA», c'est-à-dire l'architecture orientée services. Bien sûr, les Tomas Erls du monde , voudraient que vous implémentiez toutes vos couches mais avec XML et SOAP à la place.

Pour toutes les raisons ci-dessus, c'est la mauvaise façon de procéder, car vous vous coupleriez à ces proxys XML tout comme vous vous coupleriez aux couches d'application comme expliqué ci-dessus.

Au lieu de cela, utilisez la messagerie et laissez tout ce qui implémente des fonctionnalités pour eux, écoutez-les. Votre surface de service devient alors une liste de messages que vous pouvez envoyer et vous n'avez pas couplé vos opérations à votre façade de service; et vous n'avez même pas besoin de savoir quelle application ou point de terminaison implémente ces opérations, car tout ce que vous faites est de publier un message qu'un autre mécanisme de routage acheminera vers le bon consommateur!

Étant donné que vous avez découplé les façades de service des opérations réelles que vous souhaitez effectuer, vous pouvez désormais ajouter plusieurs services; en fait, c'est comme ça que Netflix le fait. Jetez un œil à ces présentations: http://www.slideshare.net/adrianco/global-netflix-platform . http://www.slideshare.net/adrianco/global-netflix-platform . Ils sont bons!


0

Il existe une nouvelle base de données SQL (ACID) de en version bêta qui aurait des propriétés de mise à l'échelle élastique. Il existe actuellement un programme bêta gratuit et je vous suggère de jeter un œil, il s'appelle NuoDB.

Apparemment, il surpasse facilement MySQL même sur une seule machine à thread, mais évolue avec bonheur à plus de 70 instances dans certains benchmarks.


Un seul fil? En quoi est-il alors une référence pertinente?
Henrik
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.