Características del diseño de un modelo de datos para NoSQL

Introducción


"¡Necesitas
correr tan rápido para mantenerte en su lugar, pero para llegar a algún lado, debes correr al menos el doble de rápido!"
(c) Alicia en el país de las maravillas


Hace algún tiempo, me pidieron que diera una conferencia a los analistas de nuestra compañía sobre el tema del diseño de modelos de datos, porque cuando nos sentamos en proyectos durante mucho tiempo (a veces durante varios años) perdemos de vista lo que está sucediendo en el mundo de TI. En nuestra empresa (simplemente sucedió), las bases de datos NoSQL no se usan en muchos proyectos (al menos por ahora), por lo que en mi conferencia les presté atención por separado usando el ejemplo de HBase e intenté orientar la presentación del material a aquellos que nunca trabajó. En particular, ilustré algunas características del diseño del modelo de datos utilizando un ejemplo que leí hace varios años en el artículo "Introducción al diseño del esquema HB ase" de Amandeep Khurana. Analizando los ejemplos, comparé entre ellos varias opciones para resolver el mismo problema a fin de transmitir mejor a la audiencia las ideas principales.


Recientemente, "no hay nada que hacer", me preguntaba (los fines de semana largos de mayo en modo de cuarentena son especialmente adecuados para esto), ¿cuánto cálculos teóricos corresponderán a la práctica? En realidad, nació la idea de este artículo. Un desarrollador que ha estado trabajando con NoSQL durante varios días puede no aprender nada nuevo de él (y, por lo tanto, puede gastar inmediatamente medio centenar). Pero para los analistas que aún no han trabajado estrechamente con NoSQL, creo que será útil para obtener una comprensión básica de las características de diseño de los modelos de datos para HBase.


Analizando un ejemplo


, NoSQL , «» «». . NoSQL . NoSQL , , . , ( ). , «» , . NoSQL . , , .


«» , :


. , ( , Linkedin). :
  • , ( )
  • / / ( )

, . (, , , , : , .., «»), /. :


user_idfriend_id

ID


HBase , :


  • , full table scan,
    • , SQL- – ; , , Impala SQL- Join’ HBase, …

ID . « ID ?» . «» ( 1 (default), ):


RowKey
1:2:3:
1:2:

. : 1, 2, … — , ID . , . (1, 2 3), – (1 2) – HBase, :


  • ( -> , -> )

:


  • : , , , RowKey = «» , «» . , « » False;
  • : : RowKey = «», . - , , ID .
  • : :
    • RowKey = «» , , ;
    • , , «» , «» .

, , « », , -. n. (n-1). (-1) , - .


  • : . (n)
  • : : , => (n)
  • : :
    • – => (n)
    • «» . « », (n-1) . , «-» - – n. ( , (2)) (n) . : «» , , :

, O(n).
, , , , - . «count», . - , «count». , «count» . .. 2 (count):


RowKey
1:2:3:count: 3
1:2:count: 2

:


  • : « ?» => (n)
  • : : , , «count» .. . (1)
  • : : , - «» . , , , => O(n)
  • , «count», , -

2 , « ». «» 3 (col).
« »: ! – , 1 (, , , «// ..»). «», NoSQL-, HBase :


RowKey
: 1: 1: 1
: 1: 1

. , :


  • : , , , «»: , True, – False => O(1)
  • : : : «ID » => O(1)
  • : : «ID » => O(1)

, , , , . , …


- . ? userID.friendID? ( 4(row)):


RowKey
.: 1
.: 1
.: 1
.: 1
.: 1

, , (1). 3 - .


«». , 4 , , , ( , HBase ). , . , userID friendID, , , . ( 5(hash)):


RowKey
dc084ef00e94aef49be885f9b01f51c01918fa783851db0dc1f72f83d33a5994: 1
dc084ef00e94aef49be885f9b01f51c0f06b7714b5ba522c3cf51328b66fe28a: 1
dc084ef00e94aef49be885f9b01f51c00d2c2e5d69df6b238754f650d56c896a: 1
1918fa783851db0dc1f72f83d33a59949ee3309645bd2c0775899fca14f311e1: 1
1918fa783851db0dc1f72f83d33a5994dc084ef00e94aef49be885f9b01f51c0: 1

, , , 4 – (1).
, :


1 (default)O(n)O(n)O(n)
2 (count)O(1)O(n)O(n)
3 (column)O(1)O(1)O(1)
4 (row)O(1)O(1)O(1)
5 (hash)O(1)O(1)O(1)

, 3-5 . , , , «», « ». 3. , , .



– . « » , (n). , , , « », «-». «-» :


  • ,

, , :


  • . n. " " – . , « » HBase . – «-»
  • . «», , . = - , «», – «». , «» «» ( 1 2). .
  • . . – ( «» , ). .

5 , , . n , , 5 .
n= 5. «» ID-:



{0: [1], 1: [4, 5, 3, 2, 1], 2: [1, 2], 3: [2, 4, 1, 5, 3], 4: [2, 1]} #  15 

{0: [1, 10800], 1: [5, 10800, 2, 10801, 4, 10802], 2: [1, 10800], 3: [3, 10800, 1, 10801, 5, 10802], 4: [2, 10800]} #  18  

{0: [1], 1: [1, 3, 2, 5, 4], 2: [1, 2], 3: [4, 1, 2, 3, 5], 4: [1, 2]} #  15 

, ID, 10 000 – , False. , «» .


Windows 10, - HBase, – Python Jupyter Notebook. 2 CPU 2 . , « », «» Python. HBase happybase, (MD5) 5 — hashlib


n = 10, 30, …. 170 – ( n) - ( 15 ).


, . . n, « » , «» , ( ).



– , . – .

3-5 «-», .
2 , , 2 3-5. , – - / HBase 2 . , .
1 , .
.

3-5 – , . 1 2 . 2 – - «count», n . - , . , ( , 1 2, ) ( " ").


– .



. 3-5 .
, , 4 5, , , 3. , – , , .


1 2, , . 2 1 – - - «» count.


:


  • 3-5 , HBase; .
  • 4 5 . , 5 . , .
  • , «-» , .


. , ( ). , thrift, happybase, , Python ( , ), HBase, Windows 10 .. , . « » .


En conclusión: recomendaciones para cualquiera que esté comenzando a diseñar modelos de datos en HBase: resumen de la experiencia previa con bases de datos relacionales y recuerde los "mandamientos":


  • Al diseñar, pasamos de los patrones de manipulación de tareas y datos, y no del modelo de dominio
  • Acceso efectivo (sin escaneo completo de la tabla) - solo por clave
  • Desnormalización
  • Las diferentes líneas pueden contener diferentes columnas.
  • La composición dinámica de las columnas.

All Articles