_Principiantes- [ver Parte 1.](https://es.community.intersystems.com/post/los-globals-son-espadas-m%C3%A1gicas-para-administrar-datos-parte-1)_ ### 3. Variantes de estructuras cuando se usan globals![](/sites/default/files/inline/images/old-sword-small.jpg) Una estructura, como un árbol ordenado, tiene varios casos especiales. Echemos un vistazo a aquellos que tienen un valor práctico para trabajar con globals. #### 3.1 Caso especial 1. Un nodo sin ramas Los globals pueden usarse no solo como una matriz, sino como variables regulares. Por ejemplo, para crear un contador: ####
Set ^counter = 0 ; setting counter
Set id=$Increment(^counter) ; atomic incrementation
Al mismo tiempo, un global puede tener ramas adicionales además de su valor. Uno no excluye al otro.
#### 3.2 Caso especial 2. Un nodo y múltiples ramas
De hecho, es una base clásica de valor clave. Y si guardamos tuplas de valores en lugar de valores, obtendremos una tabla regular con una clave primaria.
![](/sites/default/files/inline/images/key_value_table.png)
Para implementar una tabla basada en globals, tendremos que formar cadenas de valores de columna, luego guardarlas en un global por la clave primaria. Para poder dividir la cadena en columnas durante la lectura, podemos usar lo siguiente:
1. Caracteres delimitadores
Set ^t(id1) = "col11/col21/col31"
Set ^t(id2) = "col12/col22/col32"
2. Un esquema fijo, por el cual cada campo ocupa un número particular de bytes. Así es como generalmente se hace en bases de datos relacionales.
3. Una función especial [$LB](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_flistbuild) (introducida en Caché) que compone una cadena de valores.
Set ^t(id1) = $LB("col11", "col21", "col31")
Set ^t(id2) = $LB("col12", "col22", "col32")
Lo interesante es que no es difícil hacer algo similar a las claves foráneas en bases de datos relacionales que usan globals. Llamemos a tales estructuras index globals. Un índice global es un árbol suplementario para la búsqueda rápida por campos que no son una parte integral de la clave primaria del global principal. Necesita escribir código adicional para llenarlo y usarlo.
Creemos un índice global basado en la primera columna.
Set ^i("col11", id1) = 1
Set ^i("col12", id2) = 1
Para buscar rápidamente por la primera columna, deberá buscar en ^i global y encontrar las claves principales (id) correspondientes al valor necesario en la primera columna.
Al insertar un valor, podemos crear valores e índices globals para los campos necesarios. Para mayor fiabilidad, envuélvala en una transacción.
TSTART
Set ^t(id1) = $LB("col11", "col21", "col31")
Set ^i("col11", id1) = 1
TCOMMIT
Más información sobre [creando tablas en M usando globals y emulación de claves secundarias.](http://gradvs1.mgateway.com/download/extreme1.pdf)
Estas tablas funcionarán tan rápido como en las bases de datos tradicionales (o incluso más rápido) si las funciones de inserción/actualización/eliminación se escriben en COS/M y se compilan.
No he probado escenarios más complejos con acceso concurrente y transacciones paralelas.
Sin usar transacciones, la velocidad de inserción para un millón de valores fue de 778.361 inserciones/seg.
Para 300 millones de valores, la velocidad fue de 422.141 inserciones/segundo.
Cuando se utilizaron las transacciones, la velocidad alcanzó 572.082 inserciones/segundo para 50 millones de valores. Todas las operaciones se ejecutaron desde el código M compilado. Usé discos duros normales, no SSD. RAID5 con reescritura. Todo se ejecuta en una CPU Phenom II 1100T.
Para realizar la misma prueba para una base de datos SQL, necesitaríamos escribir un procedimiento almacenado que haga inserciones en un bucle. Al probar MySQL 5.5 (almacenamiento InnoDB) utilizando el mismo método, nunca obtuve más de 11K inserciones por segundo.
Tablas en un árbol de dos niveles vs. Tablas en un árbol de un nivel | |
---|---|
Contras | Pros |
Inserciones más lentas, ya que el número de nodos debe establecerse igual al número de columnas Mayor consumo de espacio en el disco duro, ya que los índices globals (como los índices de matriz) con nombres de columna ocupan espacio en el disco duro y se duplican para cada fila | Acceso más rápido a los valores de columnas particulares, ya que no necesita analizar la cadena. Según mis pruebas, es un 11,5% más rápido para 2 columnas e incluso más rápido para más columnas. Más fácil cambiar el esquema de datos Código más fácil de leer |
$a = array(
"name" => "Vince Medvedev",
"city" => "Moscow",
"threatments" => array(
"surgeries" => array("apedicectomy", "biopsy"),
"radiation" => array("gamma", "x-rays"),
"physiotherapy" => array("knee", "shoulder")
)
);
#### 3.3.3 Documentos jerárquicos: XML, JSON
También se puede almacenar fácilmente en globals y descomponerse de diferentes maneras.
**XML**
El método más fácil de descomponer XML en globals es almacenar atributos de etiqueta en nodos. Y si necesita acceso rápido a los atributos de etiqueta, podemos colocarlos en ramas separadas.
<note id=5>
<to>Alex</to>
<from>Sveta</from>
<heading>Reminder</heading>
<body>Call me tomorrow!</body>
</note>
En COS, el código se verá así:
Set ^xml("note")="id=5"
Set ^xml("note","to")="Alex"
Set ^xml("note","from")="Sveta"
Set ^xml("note","heading")="Reminder"
Set ^xml("note","body")="Call me tomorrow!"
**Nota:** Para XML, JSON y matrices asociativas, puede encontrar una serie de métodos para mostrarlos en globales. En este caso particular, no reflejamos el orden de las etiquetas anidadas en la etiqueta "note". En el **^xml** global, las etiquetas anidadas se mostrarán en orden alfabético. Para una visualización precisa del orden, puede usar el siguiente modelo, por ejemplo:
![](/sites/default/files/inline/images/xml_sort.png)
**JSON.**
El contenido de este documento JSON se muestra en la primera ilustración en la Sección 3.3.1:
var document = {
"name": "Vince Medvedev",
"city": "Moscow",
"threatments": {
"surgeries": ["apedicectomy", "biopsy"],
"radiation": ["gamma", "x-rays"],
"physiotherapy": ["knee", "shoulder"]
},
};
#### 3.3.4 Estructuras idénticas unidas por relaciones jerárquicas.
Ejemplos: estructura de oficinas de ventas, puestos de personas en una estructura MLM.
**Base de datos de inicio.** Puede usar una evaluación de fuerza de movimiento como el valor del índice de nodo global. En este caso, deberá seleccionar una rama con el mayor peso para determinar el mejor movimiento. En el global, todas las ramas en cada nivel se ordenarán por la fuerza del movimiento.
![](/sites/default/files/inline/images/debut.png)
**La estructura de las oficinas de ventas, las personas en una empresa de MLM.** Los nodos pueden almacenar algunos valores de almacenamiento en caché que reflejan las características de todo el subárbol. Por ejemplo, las ventas de este subárbol en particular. Podemos obtener información exacta sobre los logros de cualquier sucursal en cualquier momento.
![](/sites/default/files/inline/images/sales.png)
### 4. Situaciones en las que merece la pena usar globals
La primera columna contiene una lista de casos en los que el uso de globals le dará una ventaja considerable en términos de rendimiento; y la segunda, una lista de situaciones en las que simplificarán el desarrollo o el modelo de datos.
Velocidad | Conveniencia de procesamiento/presentación de datos |
---|---|
Inserción [con clasificación automática en cada nivel], [indexación por la clave primaria] Eliminación de subárbol Objetos con muchas propiedades anidadas a las que necesita acceso individual Una estructura jerárquica con la posibilidad de atravesar ramas secundarias a partir de cualquier rama, incluso una no existente Transversal de árboles en profundidad | Objetos/instancias con una gran cantidad de propiedades/instancias no requeridas [y/o anidadas] Datos sin esquema: a menudo se pueden agregar nuevas propiedades y eliminar las antiguas Necesita crear una base de datos no estándar Bases de datos de ruta y árboles de soluciones. Cuando los caminos se pueden representar convenientemente como un árbol Eliminación de estructuras jerárquicas sin usar recursividad |