2011-10-21 17 views
8

Tengo un archivo csv de 215MB que he analizado y almacenado en datos principales envueltos en mis propios objetos personalizados. El problema es que mi archivo core sqlite de datos es de alrededor de 260MB. El archivo csv contiene aproximadamente 4.5 millones de líneas de datos en el sistema de tránsito de mi ciudad (parada de autobús, horarios, rutas, etc.).¿Cómo minimizaría o comprimiría el tamaño del archivo sqlite de Core Data?

He intentado modificar los atributos para que las matrices de cadenas que representan tiempos de detención se almacenen en su lugar como archivos de NSData, pero por alguna razón el tamaño del archivo aún se mantiene en alrededor de 260MB.

No puedo enviar una aplicación de este tamaño. Dudo que alguien quiera descargar una aplicación de 260MB, incluso si eso significa que tienen todo el calendario de tránsito de la ciudad.

¿Hay alguna manera de comprimir o minimizar el espacio de almacenamiento utilizado (incluso si significa no utilizar datos básicos, estoy dispuesto a escuchar sugerencias)?

EDIT: Solo quiero proporcionar una actualización en este momento porque he estado mirando el tamaño del archivo con incredulidad. Con alguna manipulación inteligente que involucra cadenas, indexación y normalización de base de datos en general, he logrado reducir el tamaño a 6.5 MB o 2.6 MB cuando se comprime. Cerca de 105,000 objetos almacenados en Core Data que contienen todos los detalles del sistema de tránsito de la ciudad. Estoy casi llorando en este momento D ':

+0

Acabo de ver tu comentario actualizado sobre tu talla final. Muy impresionante. La compresión 100: 1 de los datos del mundo real debería enorgullecer a cualquiera. –

+0

Muy tarde, pero si echas un vistazo a la aplicación Transit, he hablado con ellos y han logrado bajar 260MB a solo ** 800KB ** – Milo

Respuesta

0

Es posible que pueda realizar una normalización de la base de datos.

Busque cualquier cosa que pueda ser redundante o que los mismos valores se almacenen en varias filas. Es probable que necesite reestructurar su base de datos para que estos valores duplicados (si los hay) se almacenen en tablas separadas y luego se haga referencia a ellos desde su fila original mediante identificadores.

0

¿Qué tamaño tiene el archivo sqlite comprimido? Si es satisfactoriamente pequeño, lo más simple sería enviarlo comprimido, luego descomprimirlo en NSCachesDirectory.

+0

Por "comprimido" quise decir comprimido con gzip, por cierto. –

+0

El archivo tiene 57.7MB cuando está comprimido. Puedes estar en algo aquí. Mi única preocupación ahora es cuánto tiempo normalmente tomaría el teléfono para descomprimirlo. –

8

A menos que su archivo CSV original esté codificado de una manera realmente tonta, parece poco probable que el tamaño no sea inferior a 100M, sin importar cuánto lo comprima. Eso todavía es muy grande para una aplicación. La solución es mover sus datos a un servicio web. Es posible que desee descargar y almacenar partes significativas en caché, pero si habla de millones de registros, parece mejor obtenerlos de un servidor. Además, tengo que creer que de vez en cuando el sistema de tránsito cambia, y sería frustrante tener que actualizar una aplicación de muchos 10s de MB cada vez que hubiera un ajuste de parada única.


lo he dicho, pero en realidad hay algunas cosas que usted puede considerar:

  • booleanos moverse en un campos de bits. Puede poner 64 booleanos en un NSUInteger. (Y no use un entero completo de 64 bits si solo necesita 8 bits. Almacene lo más pequeño que pueda.)
  • Comprima la forma de almacenar tiempos. Solo hay 1440 minutos en un día. Puedes almacenar eso en 2 bytes. Los tiempos de tránsito generalmente no son al segundo; no necesitan un CGFloat.
  • Los días de la semana y las fechas se pueden comprimir de manera similar.
  • Obviamente, debe normalizar cualquier cadena. Mire el CSV para valores de cadena duplicados en muchas líneas.
  • En general, recomendaría raw sqlite en lugar de datos básicos para este tipo de problema. Core Data trata más sobre la persistencia de objetos que el almacenamiento de datos sin procesar. El hecho de que esté viendo una hinchazón del 20% sobre CSV (que no es muy eficiente) no es una buena dirección para este problema.
  • Si quiere estar aún más ajustado y no necesita muy buenas capacidades de búsqueda, puede crear blobs de datos empaquetados. Solía ​​hacer esto en los interruptores del teléfono donde la memoria era extremadamente estrecha. Usted crea una estructura de campo de bit y asigna 5 bits para una variable, y 7 bits para otra, etc. Con eso, y un poco de tiempo mezclando las cosas para que se alineen correctamente en los límites de las palabras, puede obtener bastante apretado.

Dado que más se preocupan por su tamaño de descarga inicial, y puede estar dispuesto a ampliar sus datos más tarde para un acceso más rápido, se puede considerar la compresión muy específico de dominio. Por ejemplo, en la discusión anterior, mencioné cómo bajar a 2 bytes por un tiempo. Probablemente puedas obtener hasta 1 bytes en muchos casos almacenando los tiempos como minutos delta desde la última vez (ya que la mayoría de tus tiempos van a estar siempre aumentando en pequeños pasos si se trata de horarios de trenes y autobuses). Abandonando la base de datos, puede crear un archivo de datos muy codificado que pueda extraer en una base de datos en el primer lanzamiento.

También puede usar el conocimiento específico del dominio para codificar sus cadenas en tokens más pequeños. Si estuviera codificando el sistema de metro de Nueva York, notaría que algunas cadenas aparecen mucho, como "Avenue", "Road", "Street", "East", etc. Probablemente las codifique como ASCII no imprimible como^A,^R,^S,^E, etc. Probablemente codifique "138 Street" como dos bytes (0x8A13). Esto, por supuesto, se basa en mi conocimiento de que è (0x8a) nunca aparece en las paradas del metro de Nueva York. No es una solución general (en París podría ser un problema), pero se puede usar para comprimir datos que usted conoce muy bien. En una ciudad como Washington DC, creo que su calle con el número más alto es 38th St, y luego hay una dirección de 4 valores. Entonces puede codificar eso en dos bytes, primero un token de "calle numerada" y luego un campo de bit con 2 bits para el cuadrante y 6 bits para el número de calle. Este tipo de pensamiento puede reducir significativamente el tamaño de sus datos.

+0

Estoy totalmente de acuerdo con usted aquí. Sin embargo, la aplicación debe funcionar sin conexión, lo que significa que deben incluirse todos los datos. De lo contrario, esto realmente se me había pasado por la cabeza y sería ideal. –

+0

Sí; Estaba pensando mucho más sobre cómo almacenar mejor el CSV. Creo que hay muchas opciones. CSV realmente no es tan eficiente. Creo que cualquier cosa que puedas obtener de gzip podría mejorar con soluciones de almacenamiento más inteligentes. –

+0

Gracias Rob por su respuesta reflexiva. Revisé la base de datos y noté que se repetía mucha información, especialmente los signos distintivos, que se almacenan como cadenas. Repasando el código ahora para eliminar eso. Me gusta su sugerencia de tiempo delta y le daré una oportunidad. Con suerte puedo conseguir esta bestia por debajo de 200MB y luego gzip y extraerla a la carpeta de cachés en la primera ejecución. –

Cuestiones relacionadas