Numérisation d'un milliard de lignes dans une base de données ultra-rapide


9

Contexte

Une base de données locale contient près de 1,3 milliard de lignes uniques. Chaque ligne est indirectement associée à une latitude et une longitude spécifiques (emplacement). Chaque ligne a un timbre à date.

Cas d'utilisation

Le problème est le suivant:

  1. L'utilisateur définit une date de début / fin et une plage de valeurs (par exemple, 100 à 105).
  2. Le système rassemble toutes les lignes qui correspondent à la date donnée, regroupées par emplacement.
  3. Le système détermine les emplacements qui, pendant ces dates, ont une probabilité statistique de tomber dans la plage de valeurs donnée.
  4. Le système affiche tous les emplacements correspondants à l'utilisateur.

C'est un problème de vitesse et d'échelle.

Question

Quelle est l'architecture de solution la moins chère que vous pouvez imaginer qui permettrait à un tel système de récupérer des résultats pour les utilisateurs en moins de cinq secondes?

Système actuel

L'environnement est actuellement:

  • PostgreSQL 8.4 (la mise à niveau est possible; le changement de base de données n'est pas une option)
  • R et PL / R
  • XFS
  • WD VelociRaptor
  • 8 Go de RAM (Corsair G.Skill; 1,3 GHz)
  • Quad core Genuine Intel 7 (2,8 GHz)
  • Ubuntu 10.10

Les mises à niveau matérielles sont acceptables.

Mise à jour - Structure de la base de données

Les milliards de lignes sont dans un tableau ressemblant à:

id | taken | location_id | category | value1 | value2 | value3
  • id - Clé primaire
  • prise - Date affectée à la ligne
  • location_id - Référence à la latitude / longitude
  • catégorie - Une description des données
  • value1 .. 3 - Les autres valeurs que l'utilisateur peut interroger

La takencolonne est généralement des dates consécutives par location_id, parfois chaque emplacement a des données de 1800 à 2010 (environ 77 000 dates, beaucoup d'entre elles étant dupliquées car chaque emplacement a des données dans la même plage de dates).

Il existe sept catégories et les tableaux sont déjà divisés par catégorie (en utilisant des tableaux enfants). Chaque catégorie contient environ 190 millions de lignes. Dans un avenir proche, le nombre de lignes par catégorie dépassera le milliard.

Il y a environ 20 000 emplacements et 70 000 villes. Les emplacements sont corrélés à la ville par la latitude et la longitude. Attribuer chaque emplacement à une ville particulière signifie trouver les limites de la ville, ce qui n'est pas une tâche triviale.

Des idées

Voici quelques idées que j'ai:

  • Trouvez un service cloud pour héberger la base de données.
  • Créez une bande de raid SSD (superbe vidéo).
  • Créez un tableau qui regroupe tous les emplacements par ville (pré-calcul).

Je vous remercie!


10
"changer de base de données n'est pas une option", ce qui élimine à peu près la plupart des solutions. bonne chance!
Steven A. Lowe,

1
Il est difficile de dire sans plus d'informations sur ce que vous faites exactement avec ces enregistrements. Aussi, recherchez-vous le pire des cas pendant 5 secondes (ce qui signifie probablement que chaque enregistrement examiné et zéro emplacement correspondent)?
Guy Sirton

2
@Dave: Combien de temps le système actuel prend-il? Le système actuel utilise- t-il PostGIS ? Est location_idun geographyou geometryou fait référence à un deuxième tableau? La location_idcolonne est-elle indexée?
rwong

1
@ Thorbjørn & @Darknight - Dans la section des idées, j'énumère le pré-calcul, ce qui réduirait les données à une valeur par ville par jour (par catégorie). Le calcul pourrait se répéter chaque année, voire chaque mois, je suppose. C'était mon plan s'il n'y avait pas d'autres possibilités (les calculs prendront probablement des semaines).
Dave Jarvis

1
@Dave, beaucoup de possibilités, mais la question est de savoir ce qui vous concerne. Avez-vous déjà recherché les goulots d'étranglement actuels?

Réponses:


12

La chose la plus importante est d'être absolument certain où le goulot d'étranglement est maintenant pour un nombre donné de demandes représentatives car vous ne pouvez pas changer de base de données.

Si vous effectuez des analyses complètes de table, vous avez besoin d'index appropriés.

Si vous attendez sur les E / S, vous avez besoin de plus de mémoire pour la mise en cache (Jeff Atwood a récemment mentionné que les systèmes 24 Gb étaient accessibles sur les systèmes de bureau).

Si vous attendez sur CPU, vous devez voir si vos calculs peuvent être optimisés.

Cela nécessite un chapeau DBA pointu et un chapeau de système d'exploitation, mais cela en vaut la peine pour vous assurer d'aboyer la bonne arborescence.


Quelle que soit la façon dont vous la coupez et la coupez - même si chaque ligne ne prend que 100 octets, 1,3 milliard de lignes = 121 Go. Avec tous vos index, etc., je suis sûr que ce sera beaucoup plus. Sur une seule boîte, vous allez être lent à moins d'avoir du matériel sérieux autour du SSD + des tonnes de RAM. La méthode la moins chère consiste à évoluer sur plusieurs cases.
Subu Sankara Subramanian

4
@Subu, tu veux aller distribué? Maintenant, vous avez deux problèmes ...

Hé - avec qui je suis d'accord :) Mais c'est moins cher!
Subu Sankara Subramanian

@ Thorbjørn: Merci pour votre temps et toute votre aide. Je pense que je vais réduire l'ensemble de données à 25 millions de lignes par catégorie, puis appliquer des index à la date. Cela devrait réduire l'analyse à ~ 70000 lignes (par jour, avec une limite de deux semaines pour la plage), ce qui devrait être assez rapide.
Dave Jarvis

@Dave, vous devez toujours savoir où se trouvent vos goulots d'étranglement. Apprenez-le pendant que vous n'y êtes pas obligé .

4

Que diriez-vous de partitionner la table en plusieurs morceaux situés sur différents hôtes en fonction de l'horodatage? Ceci est évolutif horizontalement, et tant que vous avez suffisamment de boîtes, vous pouvez écrire un petit moteur d'agrégation au-dessus de ces configurations.

Si vous voyez que l'horodatage change trop, vous pouvez alors partitionner en fonction des emplacements - à nouveau évolutif horizontalement. (Espérons qu'ils n'ajoutent pas beaucoup plus de latitudes / longitudes!)


Merci pour les idées. Il y a potentiellement 77 066 dates, et de nouvelles dates seront ajoutées à l'avenir. J'ai une seule machine. Il y a 20 000 emplacements, mais la répartition par emplacement n'aiderait pas car les données à analyser couvrent tous les emplacements.
Dave Jarvis

et en quoi l'utilisation du cloud est-elle différente de la solution ci-dessus?
Chani

C'est aussi ce à quoi j'ai pensé. Une sorte de partition horizontale pour que la recherche puisse se faire en parallèle sur toutes les partitions.
davidk01

Le fractionnement sur la journée serait probablement le plus utile, résultant en 2562 tables distinctes (366 jours x 7 catégories).
Dave Jarvis

4

Le pire scénario est que la plage de dates couvre toutes les dates de votre base de données.

Vous cherchez à lire 1,3 milliard d'enregistrements et à effectuer une sorte d'analyse sur chaque enregistrement par rapport aux valeurs entrées, sur une machine physique, en moins de 5 secondes. Le résultat peut être tous les emplacements ou aucun - vous ne savez rien à l'avance.

Compte tenu de ces paramètres, je dirais probablement impossible.

Il suffit de regarder votre disque dur: le taux maximum soutenu est inférieur à 150 Mo / s. La lecture de 1,3 milliard d'enregistrements prendra plus de 5 secondes. Côté CPU, vous ne pourrez pas faire d'analyse statistique sur 1,3 milliard d'enregistrements en 5 secondes.

Votre seul espoir (tm :-)) est de trouver une sorte de fonction de recherche basée sur les valeurs entrées par l'utilisateur qui restreindra la recherche (de quelques ordres de grandeur). Vous pouvez calculer cette fonction de recherche hors ligne. Sans en savoir plus sur les critères de correspondance exacts, je ne pense pas que quiconque puisse vous dire comment le faire, mais un exemple serait de partitionner la plage de valeurs en un intervalle discret et de créer une recherche qui vous donnera tous les enregistrements de cet intervalle. Tant que l'intervalle est suffisamment petit, vous pouvez y faire un vrai travail, par exemple l'élagage des entrées qui ne correspondent pas à la valeur entrée par l'utilisateur. Fondamentalement, échange d'espace contre du temps.

Il peut être possible de conserver tous les enregistrements (ou au moins la partie importante) en mémoire. Probablement pas en 8 Go. Cela éliminera au moins la partie d'E / S du disque, même si la bande passante mémoire peut être insuffisante pour tout parcourir en 5 secondes. En tout cas, c'est une autre technique pour accélérer ce genre d'applications (combiner avec ma suggestion précédente).

Vous mentionnez l'utilisation d'un service cloud. Oui, si vous payez pour suffisamment de CPU et de muscle IO et partitionnez votre base de données sur de nombreux serveurs, vous pouvez la forcer / diviser et la conquérir.


Merci pour la réponse. Les mises à niveau matérielles sont une considération, selon les idées que j'ai énumérées. Une solution inférieure à 750 USD serait idéale.
Dave Jarvis

2

J'appuie le commentaire de rwong sur la question: PostgreSQL propose des types d'index et des outils appropriés (index GIST, index GIN, Postgis, types géométriques) de telle manière que les géodonnées et les données liées à l'heure / date devraient être consultables le long de ces critères sans trop de problèmes.

Si vos requêtes sur ces critères prennent quelques secondes, cela signifie probablement qu'aucun index de ce type n'est utilisé. Pouvez-vous confirmer que vous avez enquêté sur ces questions comme il convient?


Je vous remercie. Les sept tables enfants sont regroupées sur l'emplacement, la date et la catégorie à l'aide d'un btree. J'ai fait des recherches sur les indices GIN l'année dernière et ils n'ont pas aidé (ou ne voulaient pas), si je me souviens bien.
Dave Jarvis

2
L'indexation de l'emplacement basé sur B-Tree n'est pas du tout utile compte tenu du type de recherches que vous recherchez. Vous avez besoin d'un index inversé qui fonctionne avec les opérateurs nécessaires, ce qui dans le cas de Postgis signifie généralement GIST. Vous voudrez peut-être mettre en évidence quelques-unes des requêtes lentes ...
Denis de Bernardy

1

Étant donné que vous utilisez PostgreSQL et des données de latitude / longitude, vous devez également utiliser PostGIS, de cette façon, vous pouvez ajouter un index spatial GiST à votre base de données pour accélérer les choses.

J'ai une telle table (avec 350k lignes) avec une configuration beaucoup plus petite que la vôtre (2 cœurs et à peine 2 Go de RAM) mais les recherches prennent moins d'une seconde.


0

Peut-être pourriez-vous casser un modèle relationnel comme Essbase l'a fait avec leur architecture OLAP: Essbase Wikipedia

Ce que je veux dire, c'est créer une table par ville, se retrouvant ainsi avec plus de 1000 tables. Pas une table comme vous l'avez suggéré, mais plusieurs. Indexez chaque table par date et lieu. De nombreuses tables, de nombreux index -> plus rapide.


Merci pour la note. Il existe plus de 70 000 villes, et de nombreuses valeurs de latitude / longitude différentes se situent dans une zone de ville spécifique.
Dave Jarvis

@Dave: pouvez-vous construire un diagramme de voronoi pour les villes et classer les valeurs lat / lon en pavages? (c.-à-d. si cela semble aléatoire, que ce soit le cas.) Ensuite, pendant la recherche, vous chercherez toutes les villes dont la tessellation touche les plages lat / lon de la requête. Si la tessellation voronoï est trop lente, les cases carrées (par exemple 5 deg lat x 5 deg lon) peuvent valoir la peine d'être essayées.
rwong

0

En ce qui concerne votre idée de trouver un service cloud pour héberger la base de données, avez-vous déjà rencontré SimpleGeo ? Ils viennent de couper le ruban sur un service de stockage qui est apparemment "spécifiquement réglé pour stocker et interroger les données de localisation vraiment, très rapidement" - bien que le coût de stockage et d'interrogation sur plus d'un milliard de lignes puisse rendre cette approche irréalisable.


-2

vous vous attendez à ce qu'un vélo roule sur l'autoroute. actuellement, vous cherchez une solution pour résoudre ce problème uniquement, vous ne prévoyez pas le problème si vous avez 2 milliards d'enregistrements? l'évolutivité doit être abordée. la réponse est des bases de données d'objets à usage simple. ex: cache intersystèmes

et croyez vous moi je ne suis pas intersystèmes ;-)

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.