2008-11-04 9 views
8

Version courteVous cherchez à travers les partitions?

Si je divisé mes utilisateurs en tessons, comment puis-je offrir une « recherche de l'utilisateur »? Évidemment, je ne veux pas que toutes les recherches atteignent chaque fragment.

Version longue

Par tesson, je veux dire avoir plusieurs bases de données où chaque contient une fraction de l'ensemble des données. Pour un exemple (naïf), les bases de données UserA, UserB, etc. peuvent contenir des utilisateurs dont le nom commence par "A", "B", etc. Lorsqu'un nouvel utilisateur s'inscrit, j'examine simplement son nom et le place dans le bon base de données. Quand un utilisateur de retour se connecte, je regarde à nouveau son nom pour déterminer la base de données correcte pour tirer ses informations. L'avantage de la réplication sharding vs read est que la réplication en lecture ne met pas à l'échelle vos écritures. Toutes les écritures qui vont au maître doivent aller à chaque esclave. Dans un sens, ils portent tous la même charge d'écriture, même si la charge de lecture est distribuée.

Pendant ce temps, les fragments ne se soucient pas de l'écriture de l'autre. Si Brian s'inscrit sur le fragment UserB, le fragment UserA n'a pas besoin d'en entendre parler. Si Brian envoie un message à Alex, je peux enregistrer ce fait sur les fragments UserA et UserB. De cette façon, quand Alex ou Brian se connecte, il peut récupérer tous ses messages envoyés et reçus depuis son propre fragment sans interroger tous les fragments.

Jusqu'ici, tout va bien. Qu'en est-il des recherches? Dans cet exemple, si Brian recherche "Alex", je peux vérifier UserA. Mais que faire s'il recherche Alex par son nom de famille, "Smith"? Il y a des Smiths dans chaque fragment. De là, je vois deux options:

  1. Demandez à l'application de rechercher des Smith sur chaque fragment. Cela peut être fait lentement (en interrogeant chaque fragment successivement) ou rapidement (en interrogeant chaque fragment en parallèle), mais de toute façon, chaque fragment doit être impliqué dans chaque recherche. De la même manière que la réplication en lecture ne met pas à l'échelle les écritures, les recherches effectuées sur chaque fragment n'évoluent pas vos recherches. Vous pouvez atteindre un moment où votre volume de recherche est suffisamment élevé pour submerger chaque fragment, et l'ajout de fragments ne vous aide pas, car ils ont tous le même volume.
  2. Une sorte d'indexation qui tolère elle-même le sharding. Par exemple, disons que j'ai un nombre constant de champs par lesquels je veux rechercher: prénom et nom. En plus de UserA, UserB, etc. J'ai aussi IndexA, IndexB, etc. Quand un nouvel utilisateur s'enregistre, je le joins à chaque index où je veux qu'il soit trouvé. J'ai donc mis Alex Smith dans IndexA et IndexS, et il peut être trouvé sur "Alex" ou "Smith", mais pas de sous-chaînes. De cette manière, vous n'avez pas besoin d'interroger chaque fragment, donc la recherche peut être évolutive.

La recherche peut-elle être mise à l'échelle? Si oui, cette approche d'indexation est-elle la bonne? Y en a-t-il d'autres?

Répondre

2

Je suppose que vous parlez de tessons à la: http://highscalability.com/unorthodox-approach-database-design-coming-shard

Si vous lisez cet article, il va dans des détails sur exactement votre question, mais longue réponse courte, vous écrivez du code d'application personnalisé pour apporter votre éclats disparates ensemble. Vous pouvez effectuer un hachage intelligent pour interroger des fragments individuels et insérer des données dans des fragments. Vous devez poser une question plus précise pour obtenir une réponse plus précise.

+0

Merci. J'ai vraiment lu ce site intensivement. J'ai essayé de clarifier ma question ci-dessus; qui, espérons-le, est au-delà de l'article que vous avez utilement lié. –

1

Vous avez réellement besoin de chaque recherche pour atteindre chaque fragment, ou au moins chaque recherche doit être effectuée par rapport à un index qui contient les données de tous les fragments, ce qui équivaut à la même chose.

Probablement vous partitionnez basé sur une seule propriété de l'utilisateur, probablement un hachage du nom d'utilisateur. Si votre fonctionnalité de recherche permet à l'utilisateur de rechercher en fonction d'autres propriétés de l'utilisateur, il est clair qu'il n'y a pas de fragment ou de sous-ensemble de fragments pouvant satisfaire une requête, car tout fragment peut contenir des utilisateurs correspondant à la requête. Vous ne pouvez exclure aucun fragment avant d'effectuer la recherche, ce qui implique que vous devez exécuter la requête sur tous les fragments.

+0

S'il vous plaît voir ma clarification ci-dessus. –

7

Il n'y a pas de solution miracle.

La recherche successive de chaque fragment est hors de question, évidemment, en raison de la latence incroyablement élevée que vous encourez.

Donc, vous voulez rechercher en parallèle, si vous devez.

Il existe deux options réalistes et vous les avez déjà répertoriées: l'indexation et la recherche parallélisée. Permettez-moi d'entrer dans un peu plus de détails sur la façon dont vous allez les concevoir. L'idée clé que vous pouvez utiliser est que dans la recherche, vous avez rarement besoin de l'ensemble complet des résultats. Vous avez seulement besoin de la première (ou nième) page de résultats. Il y a donc beaucoup de marge de manœuvre que vous pouvez utiliser pour réduire le temps de réponse.

indexation

Si vous connaissez les attributs sur lesquels les utilisateurs seront recherchés, vous pouvez créer sur mesure, des index séparés pour eux. Vous pouvez créer votre propre inverted index, qui pointera vers le tuple (shard, recordId) pour chaque terme de recherche, ou vous pouvez le stocker dans la base de données. Mise à jour paresseusement, et de manière asynchrone. Je ne connais pas les exigences de votre application, il pourrait même être possible de simplement reconstruire l'index tous les soirs (ce qui signifie que vous n'aurez pas les entrées les plus récentes d'un jour donné - mais cela pourrait vous convenir). Assurez-vous d'optimiser cet index pour la taille afin qu'il puisse tenir dans la mémoire; Notez que vous pouvez partitionner cet index, si nécessaire. Naturellement, si les gens peuvent rechercher quelque chose comme "lastname='Smith' OR lastname='Jones'", vous pouvez lire l'index de Smith, lire l'index de Jones et calculer l'union - vous n'avez pas besoin de stocker toutes les requêtes possibles, juste leurs parties de construction.

Recherche parallèle

Pour chaque requête, envoyer des demandes à chaque tesson sauf si vous savez que tesson chercher parce que la recherche se trouve être sur la clé de répartition. Rendre les demandes asynchrones. Répondre à l'utilisateur dès que vous obtenez la première page de résultats; collectez le reste et mettez en cache localement, de sorte que si l'utilisateur tape "suivant", les résultats seront prêts et vous n'aurez plus besoin de re-interroger les serveurs. De cette façon, si certains serveurs prennent plus de temps que d'autres, vous n'avez pas besoin de les attendre pour traiter la demande.

Pendant que vous y êtes, consignez les temps de réponse des serveurs partagés pour observer les problèmes potentiels de données inégales et/ou de distribution de charge.

1

Vous voudrez peut-être regarder Sphinx (http://www.sphinxsearch.com/articles.html). Il prend en charge la recherche distribuée. GigaSpaces prend en charge les requêtes et les fusions parallèles. Cela peut également être fait avec MySQL Proxy (http://jan.kneschke.de/2008/6/2/mysql-proxy-merging-resultsets).

Pour créer un type de défait indexé non partitionné, le but de la partition est en premier lieu :-) Un index centralisé ne fonctionnera probablement pas si des fragments étaient nécessaires. Je pense que tous les fragments doivent être frappés en parallèle.Les résultats doivent être filtrés, classés, triés, regroupés et les résultats fusionnés à partir de tous les fragments. Si les éclats eux-mêmes deviennent débordés, vous devez faire l'habituel (reshard, scale up, etc) pour les submerger à nouveau.

0

Les RDBM ne sont pas un bon outil pour la recherche textuelle. Vous serez beaucoup mieux en regardant Solr. La différence de performance entre Solr et la base de données sera de l'ordre de 100X.

Questions connexes