L'un des défis liés à la conception d'une nouvelle base de données est que vous ne savez pas, par exemple, quelle sera la taille des tables jusqu'à ce qu'elles soient réellement remplies d'une bonne quantité de données. Mais si la conception doit prendre en compte les éventuels problèmes d'évolutivité, vous ne pouvez pas la déployer pour obtenir ces données tant que l'estimation n'est pas terminée. Une façon de contourner ce problème consiste à prototyper agressivement des choses. Utilisez à cette fin du matériel de mise en scène sur lequel les nouvelles applications peuvent vivre temporairement tout en triant des détails comme celui-ci. Vous pouvez simplement tenir compte du fait que vous devrez déplacer l'application et éventuellement la reconcevoir après quelques mois, lorsque vous aurez une meilleure idée des données qui y seront affichées.
L'autre façon de contourner ce problème de poule/œuf est d'écrire un générateur de données. Construisez suffisamment de données d'échantillon à la main pour voir à quoi elles ressemblent, à quel point elles sont denses et comment leurs valeurs sont distribuées. Ensuite, écrivez quelque chose qui prend ces statistiques et produit un ensemble de données plus grand similaire à celui-ci. Vous n'obtiendrez jamais que ce soit parfait, mais ce n'est pas nécessaire. La génération d'ensembles de données géants, même avec quelques défauts, reste le meilleur moyen disponible pour estimer la taille de la base de données. Il y a tellement de sources de surcharge qu'il est difficile de tenir compte du fait que toute taille de table et d'index mesurée, basée sur quelque chose comme vos données, sera bien plus précise que toute autre approche. Il y a une raison pour laquelle je finis par répondre à de nombreuses questions sur les problèmes liés aux performances en utilisant pgbench pour créer d'abord une base de données de la taille appropriée.
La génération de données n'est cependant pas facile. Générer des horodatages réalistes en particulier est toujours ennuyeux. Et quelle que soit l'efficacité avec laquelle vous pensez les avoir écrites, leur exécution prend généralement plus de temps que prévu, et encore plus de temps pour intégrer les données résultantes dans une base de données et les indexer correctement.
Et cela continue d'être le cas, peu importe combien de fois vous l'avez fait, car même si vous faites tout correctement, la loi de Murphy s'imposera pour rendre le travail pénible malgré tout. Mes ordinateurs à la maison sont tous construits à partir de matériel informatique relativement bon marché. Ce n'est pas le moins cher disponible - j'ai des normes - mais certainement pas en utilisant la même qualité que je recommanderais aux gens de rechercher dans un serveur. Le problème de génération de données de cette semaine a rappelé pourquoi un meilleur matériel vaut ce qu'il en coûte pour un travail critique pour l'entreprise.
Après avoir généré quelques milliards de lignes de données et observé cette importation pendant 10 heures, je n'étais pas content de voir tout le travail s'arrêter comme ceci :
psql:load.sql:10: ERROR: invalid input syntax for type timestamp: "201^Q-04-14 12:17:55"
CONTEXT: COPY testdata, line 181782001, column some_timestamp: "201^Q-04-14 12:17:55"
Il s'avère que quelque part au milieu de l'écriture des 250 Go de données de test que j'ai générées, l'une des lignes de sortie était corrompue. Deux bits ont été inversés et les données écrites étaient erronées. Je ne sais pas où cela s'est produit avec certitude.
La mémoire est le suspect le plus probable. Les vrais serveurs utilisent la RAM ECC, et pour une bonne raison. Si vous surveillez un système avec beaucoup de RAM, le nombre d'erreurs corrigées silencieusement par ECC peut être choquant. La RAM que j'utilise à la maison est bonne, mais les taux d'erreur sur n'importe quelle mémoire sans capacités de détection/correction d'erreurs seront plus élevés que vous ne le souhaiteriez - et ne seront jamais détectés à moins qu'ils ne se produisent dans le code qui entraîne un plantage du système. Le travail de génération de données est efficace pour exposer ces problèmes, car il place généralement au moins un processeur sur votre serveur sous une charge importante pendant potentiellement des jours d'affilée. S'il y a une instabilité dans votre système, le faire chauffer et le laisser fonctionner pendant une longue période l'aggravera.
Une deuxième couche de protection contre ce type de corruption consiste à placer des sommes de contrôle sur les données en cours d'écriture sur le disque, pour se protéger contre les erreurs d'écriture puis de relecture des données. La somme de contrôle de bloc effectuée par le système de fichiers ZFS en est l'une des meilleures implémentations. Dans mon cas, que j'aie utilisé ZFS ou non n'a peut-être pas fait de différence. Si les bits étaient retournés avant que la somme de contrôle du bloc ne se produise, j'aurais écrit des données indésirables - avec une somme de contrôle indésirable pour y correspondre - peu importe.
Ma prochaine étape consistait à utiliser le split utilitaire pour prendre mon fichier géant et le casser en plus petits morceaux - encore quelques heures à attendre que cela se termine. Ensuite, je pourrais commencer à charger les bons fichiers pendant que je corrigeais le mauvais.
Étant donné que les fichiers résultants étaient de 13 Go chacun et que mon serveur dispose de 16 Go de RAM, bien que je puisse corriger cette faute de frappe en utilisant vi. Théoriquement, cela devrait être le cas, mais je commence à avoir des doutes compte tenu du temps que j'ai attendu pour que le fichier soit réécrit par la suite :
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21495 gsmith 20 0 8542m 8.3g 1544 R 98 53.0 419:56.70 vi datafile-ag
Cela fait 7 bonnes heures que j'attends que cette faute de frappe soit corrigée, afin que je puisse terminer le chargement des données de test. Comme je le disais, la génération de données sérieuses n'est jamais facile.