Uno de los desafíos cuando se trata de un nuevo diseño de base de datos es que no sabe qué tan grandes terminarán siendo las tablas hasta que realmente se llenen con una buena cantidad de datos. Pero si el diseño tiene que tener en cuenta las eventuales preocupaciones de escalabilidad, no puede implementarlo para obtener esos datos hasta que se realice la estimación. Una forma de evitar esto es prototipar agresivamente las cosas. Use hardware de preparación para este propósito en el que las nuevas aplicaciones puedan vivir temporalmente mientras se clasifican detalles como este. Solo puede tener en cuenta que necesitará mover la aplicación y posiblemente rediseñarla después de unos meses, cuando tenga una mejor idea de qué datos se mostrarán en ella.
La otra forma de sortear este problema del huevo y la gallina es escribir un generador de datos. Construya suficientes datos de muestra a mano para ver cómo se ven, qué tan densos son y cómo se distribuyen sus valores. Luego escriba algo que tome esas estadísticas y produzca un conjunto de datos más grande similar a este. Nunca conseguirás que sea perfecto, pero no tiene por qué serlo. La generación de conjuntos de datos gigantes, incluso con algunas fallas, sigue siendo la mejor manera disponible para hacer una estimación del tamaño de la base de datos. Hay tantas fuentes de gastos generales que es difícil tener en cuenta que cualquier tamaño de tabla e índice medido, basado en algo como sus datos, será mucho más preciso que cualquier otro enfoque. Hay una razón por la que termino respondiendo muchas preguntas sobre inquietudes relacionadas con el rendimiento usando pgbench para crear primero una base de datos del tamaño adecuado.
Sin embargo, la generación de datos no es fácil. En particular, generar marcas de tiempo realistas siempre es molesto. Y no importa cuán eficientemente crea que los ha escrito, por lo general tardan más de lo esperado en ejecutarse, e incluso más en obtener los datos resultantes en una base de datos e indexarlos correctamente.
Y ese sigue siendo el caso sin importar cuántas veces haya hecho esto, porque incluso si hace todo bien, la Ley de Murphy se entrometerá para hacer que el trabajo sea doloroso de todos modos. Todas mis computadoras en casa están construidas con hardware de PC relativamente barato. No es el material más barato disponible, tengo estándares, pero ciertamente no usa la misma calidad que recomendaría que la gente busque en un servidor. El problema de generación de datos de esta semana recordó por qué un mejor hardware vale lo que cuesta para el trabajo crítico del negocio.
Después de generar unos cuantos miles de millones de filas de datos y ver esa importación durante 10 horas, no me complació que todo el trabajo abortara así:
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"
Resulta que, en algún lugar a la mitad de la escritura de los 250 GB de datos de prueba que generé, una de las líneas de salida estaba dañada. Se voltearon dos bits y los datos escritos eran incorrectos. No sé con certeza dónde sucedió eso.
La memoria es el sospechoso más probable. Los servidores reales usan RAM ECC, y por una buena razón. Si supervisa un sistema con mucha RAM, la cantidad de errores corregidos silenciosamente por ECC puede ser impactante. La memoria RAM que uso en casa es buena, pero las tasas de error en cualquier memoria sin capacidades de detección/corrección de errores serán más altas de lo que le gustaría, y nunca se detectarán a menos que ocurran en el código que provoque un bloqueo del sistema. El trabajo de generación de datos es bueno para exponer estos problemas, porque normalmente pone al menos una CPU en su servidor bajo carga pesada durante potencialmente días seguidos. Si hay alguna inestabilidad en su sistema, calentarlo y dejarlo funcionar durante mucho tiempo lo agravará.
Una segunda capa de protección contra este tipo de corrupción es poner sumas de verificación en los datos que se escriben en el disco, para protegerse contra errores al escribir y luego volver a leer los datos. La suma de comprobación de bloques realizada por el sistema de archivos ZFS es una de las mejores implementaciones de eso. En mi caso, si hubiera usado ZFS o no, puede que no haya hecho ninguna diferencia. Si los bits se cambiaron antes de que ocurriera la suma de verificación del bloque, habría eliminado los datos no deseados, con una suma de verificación no deseada para que coincida, independientemente.
Mi siguiente paso fue usar la split utilidad para tomar mi archivo gigante y dividirlo en pedazos más pequeños, otro par de horas para esperar a que termine. Entonces podría empezar a cargar los archivos buenos mientras arreglaba el malo.
Dado que los archivos resultantes tenían 13 GB cada uno y mi único servidor tiene 16 GB de RAM, aunque podría corregir este error tipográfico de un carácter usando vi. En teoría, ese debería ser el caso, pero estoy empezando a tener mis dudas dado el tiempo que he estado esperando a que el archivo vuelva a escribirse después:
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
Son 7 horas sólidas que he estado esperando solo para que se solucione este error tipográfico de un carácter, para poder terminar de cargar los datos de prueba. Como decía, la generación de datos serios nunca es fácil.