Mostrando las entradas con la etiqueta Sql server. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Sql server. Mostrar todas las entradas

domingo, 14 de junio de 2020

Programación reactiva + bases de datos relacionales = R2DBC


Al carecer de una API estándar y la falta de disponibilidad de controladores, un equipo de Pivotal comenzó a investigar la idea de una API relacional reactiva que sería ideal para fines de programación reactiva. Y en ese momento nació, R2DBC que significa Conectividad de base de datos relacional reactiva.

Entre las características de R2DBC podemos nombrar: 

R2DBC se basa en la especificación de Reactive Streams, que proporciona una API sin bloqueo totalmente reactiva.

Trabaja con bases de datos relacionales. A diferencia de la naturaleza bloqueante de JDBC, R2DBC le permite trabajar con bases de datos SQL utilizando una API reactiva.

Admite soluciones escalables. Con Reactive Streams, R2DBC le permite pasar del modelo clásico de "un subproceso por conexión" a un enfoque más potente y escalable.

Proporciona una especificación abierta. R2DBC es una especificación abierta y establece una interfaz de proveedor de servicios (SPI) para que los proveedores de controladores implementen y los clientes los consuman.

Actualmente existen las siguientes implementaciones : 
  • cloud-spanner-r2dbc: controlador para Google Cloud Spanner
  • jasync-sql: contenedor R2DBC para Java & Kotlin Async Database Driver para MySQL y PostgreSQL escrito en Kotlin.
  • r2dbc-h2: controlador nativo implementado para H2 como base de datos de prueba.
  • r2dbc-mariadb: controlador nativo implementado para MariaDB.
  • r2dbc-mssql: controlador nativo implementado para Microsoft SQL Server.
  • r2dbc-mysql: controlador nativo implementado para MySQL.
  • r2dbc-postgres: controlador nativo implementado para PostgreSQL.
Los estándares existentes, basados ​​en el bloqueo de I/O, cortan la programación reactiva de los usuarios de bases de datos relacionales. R2DBC especifica una nueva API para permitir código reactivo que funciona de manera eficiente con bases de datos relacionales.

R2DBC es una especificación diseñada desde cero para la programación reactiva con bases de datos SQL. Define un SPI sin bloqueo para implementadores de controladores de bases de datos y autores de bibliotecas de clientes. Los controladores R2DBC implementan completamente el protocolo de conexión de la base de datos sobre una capa de I/O sin bloqueo.

R2DBC está pensado principalmente como un SPI del controlador para ser consumido por las bibliotecas del cliente y no para ser utilizado directamente en el código de la aplicación.

R2DBC admite aplicaciones nativas en la nube que utilizan bases de datos relacionales como PostgreSQL, MySQL y otras. Los desarrolladores de aplicaciones son libres de elegir la base de datos adecuada para el trabajo sin estar limitados por las API.

Spring Data R2DBC, parte de la familia Spring Data, facilita la implementación de repositorios basados en R2DBC. Spring Data R2DBC aplica abstracciones de la familia de Spring y soporte de repositorio para R2DBC. Facilita la creación de aplicaciones basadas en Spring que utilizan tecnologías de acceso a datos relacionales en una stack de aplicaciones reactivas.

Spring Data R2DBC pretende ser conceptualmente fácil. Para lograr esto, NO ofrece almacenamiento en caché, carga diferida, escritura detrás o muchas otras características de los marcos ORM. Esto hace que Spring Data R2DBC sea un mapeador de objetos simple, limitado y con opiniones.

Spring Data R2DBC permite un enfoque funcional para interactuar con su base de datos proporcionando DatabaseClient como el punto de entrada para las aplicaciones.

Veamos un ejemplo con postgres : 

PostgresqlConnectionFactory connectionFactory = new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
.host(…)
.database(…)
.username(…)
.password(…).build());

DatabaseClient client = DatabaseClient.create(connectionFactory);

Mono<Integer> affectedRows = client.execute()
        .sql("UPDATE person SET name = 'Joe'")
        .fetch().rowsUpdated();

Flux<Person> all = client.execute()
        .sql("SELECT id, name FROM person")
        .as(Person.class)
        .fetch().all();

Otro enfoque para atacar el bloqueo de JDBC es Fibers. Fibers como una abstracción ligera que convertirá las API de bloqueo en no bloqueantes. Esto es posible mediante el cambio de pila tan pronto como una invocación ... Pero eso es otra Historia y va ha ser contada en otro post ... 

Dejo links: 

domingo, 26 de mayo de 2019

Que son los System Keyspaces en Cassandra?

Cassandra tiene su propio almacenamiento para realizar un seguimiento de los metadatos sobre el clúster y el nodo local. Esto es similar a la forma en que Microsoft SQL Server mantiene las metabases de datos master y tempdb. El master se usa para mantener información sobre el espacio en disco, el uso de este, la configuración del sistema y las notas generales de instalación del servidor; el tempdb se utiliza como un espacio de trabajo para almacenar resultados intermedios y realizar tareas generales. La base de datos Oracle siempre tiene un tablespace llamado SYSTEM, usado para propósitos similares. Los System Keyspaces de Cassandra se utilizan de forma muy similar a estos.

Si vamos a cqlsh y echamos un vistazo rápido a las tablas System Keyspaces en Cassandra, si hacemos :

cqlsh> DESCRIBE TABLES;

Al observar estas tablas, vemos que muchas de ellas están relacionadas con los conceptos que se analizado en post anteriores :

  • La información sobre la estructura del clúster comunicada a través de gossip se almacena en system.local y system.peers. Estas tablas contienen información sobre el nodo local y otros nodos en el clúster, incluidas direcciones IP, ubicaciones por centro de datos y rack, CQL y versiones de protocolo.
  • system.range_xfers y system.available_ranges rastrean los rangos de token administrados por cada nodo y cualquier rango que necesite asignación.
  • Los system_schema.keyspaces, system_schema.tables y system_schema.columns almacenan las definiciones de los espacios de claves, tablas e índices definidos para el clúster.
  • La construcción de vistas materializadas se rastrea en las tablas system.materialized_views_builds_in_progress y system.built_materialized_views, lo que da como resultado las vistas disponibles en system_schema.materialized_views.
  • Extensiones proporcionadas por el usuario, como system_schema.types para tipos definidos por el usuario, system_schema.triggers para activadores configurados por tabla, system_schema. funciones para funciones definidas por el usuario, y system_schema.aggregates para agregados definidos por el usuario.
  • La tabla system.paxos almacena el estado de las transacciones en curso, mientras que la tabla system.batchlog almacena el estado de los lotes atómicos.


Volvamos a cqlsh para echar un vistazo rápido a los atributos System Keyspaces de Cassandra:

cqlsh> USE system;
cqlsh:system> DESCRIBE KEYSPACE;
CREATE KEYSPACE system WITH replication = {'class': 'LocalStrategy'} AND durable_writes = true;
...

Al observar la primera declaración en la salida, vemos que el espacio System Keyspaces está usando la estrategia de replicación LocalStrategy, lo que significa que esta información está destinada para uso interno y no se replica en otros nodos.

sábado, 2 de junio de 2018

Entendiendo el plan de ejecución de una consulta SQL


Muchas veces tenemos problemas de performance y como unos campeones vamos a ver el plan de ejecución pero no entendemos nada :(

¿Qué debo buscar primero?

Todos los motores de bases de datos deberían indicar al menos dos cosas en el plan de ejecución sobre la consulta que estamos investigando:

  • Costo
  • Cantidad de registros

Es importante buscar el costo y la cantidad de registros en cada parte de la consulta porque nos va a dar una idea donde trabajar..

Depende de la herramienta que usen, es más fácil encontrar uno u otro, por ejemplo Oracle directamente en el EXPLAIN PLAN tenes la columna Cost y Rows.

En SQL Server, si vemos el plan de ejecución en el Management Studio podemos ver el Subtree Cost que es el acumulado de la tarea actual más todas las tareas anteriores que ejecutó (en esa rama). Además, el grosor de la flecha (viendo el plan gráficamente) muestra la cantidad de registros que se mueven en esa consulta.



¿Por qué hay un Sort en mi plan si no hago Order By en la query?

Usualmente esto puede suceder cuando el JOIN se resuelve con el algoritmo MERGE (o sort-merge join). En SQL Server se ve está manera:



El Sort es costoso cómo se ve, pero es peor que resolverlo con un “Loop”. Esto se soluciona con índices ya que con un índice, el ordenamiento es mucho más simple.

¿Que cosas NO deberían aparecer en el plan de ejecución?

En bases de datos relacionales (me refiero a las OLTP y no a los DW donde se hace adrede), no deberíamos jamás encontrarnos con un “Table Scan”. Si aparece un table scan, es porque esa tabla no tiene un Cluster Index (y probablemente tampoco una PK). Cuando las tablas no tienen un Cluster Index no se guardan de manera ordenada y por lo tanto, para hacer una búsqueda el motor se ve obligado a escanear la tabla entera.

¿La base está eligiendo el plan correcto?

Si pensas que existe la posibilidad de que la base no esté eligiendo el plan de ejecución correcto, es porque seguramente tenes que actualizar la estadísticas. No pretendan forzar a la base de datos a elegir un índice específico (aunque puedas hacerlo). Si la base no elige tu índice, seguro tiene un motivo.

viernes, 13 de abril de 2018

Estadísticas de las base de datos relacionales.

Para que una base de datos relacional pueda resolver una consulta SQL de forma óptima necesita conocer los datos físicos de cada tabla, índice o cluster que intervienen en ella. Estos datos se almacenan en el diccionario de datos.

En oracle pueden ser consultadas usando las vistas adecuadas: dba_tables, dba_tab_statistics, dba_tab_col_statistics, dba_tab_histograms, dba_indexes, dba_ind_statistics… etc.

En concreto, es el optimizador quién de todos los planes de ejecución posibles analiza estos datos estadísticos para evaluar cuál de todos supone un menor coste en términos de I/O y uso de CPU.

Las estadísticas deben reflejar verazmente el estado físico de los objetos, y conforme vayan sufriendo transformaciones éstas se irán quedando obsoletas. Es por esto por lo que hay que recopilar las estadísticas de nuevo a medida que ya no reflejen la situación real de los objetos a los que describen.

Si una tabla no posee estadísticas, el motor de base de datos puede recopilar ciertos datos dinámicamente en el momento de la consulta. Esto se llama muestreo dinámico “dynamic sampling”.

Las estadísticas se pueden recopilar  manual o automáticamente. Por omisión, Oracle recopila las estadísticas a través del job programado con scheduler en una ventana de tiempo predefinida: por ejemplo de lunes a viernes de 22:00 a 6:00 y sábados y domingos completos. Durante esta recopilación automática se toman datos de tablas sin estadísticas o con estadísticas obsoletas (que han sufrido más de 10% de modificaciones desde la anterior toma de datos) pero antes debe haberse configurado el parámetro STATISTICS_LEVEL a un valor distinto de BASIC.

En oracle para seguir el número de registros modificados existe la vista existe all_tab_modifications. Ésta muestra el número aproximado de inserciones, modificaciones, borrados y truncados que ha sufrido la tabla desde la última recopilación. La vista es consultable por el usuario pero hay que tener en cuenta que estos datos no son visibles inmediatamente. Existe un retardo de unos minutos para evitar que la escritura interfiera en el rendimiento.

Para recopilar las estadísticas manualmente hay diferentes funciones dependiendo el motor por ejemplo en oracle hay que usar el paquete DBMS_STATS. Dicho paquete tiene métodos para:

  • Recopilar estadísticas.
  • Borrar estadísticas.
  • Guardar y asignar estadísticas.
  • Crear o borrar tablas donde guardar juegos de estadísticas.
  • Bloquear y desbloquear las estadísticas de las tablas.
  • Retornar las estadísticas que tenía una tabla en un momento dado.

En Oracle podemos ejecutar las estadísticas para todos los esquemas de la siguiente forma:

SQL> exec dbms_stats.gather_database_stats;
Procedimiento PL/SQL terminado correctamente.

En Postgres por ejemplo existe una herramienta llamada ANALYZE que permite correr las estadísticas de forma manual :

ANALYZE [ VERBOSE ] [ table_name [ ( column_name [, ...] ) ] ]

Como se puede ver hay diferentes modos de correr esto pero lo más común sería:

ANALYZE VERBOSE users;

En sql server, tambien podemos actualizar las estadísticas utilizando UPDATE STATISTICS o el  stored procedure sp_updatestats, veamos unos ejemplos:

USE AdventureWorks2012;
GO

UPDATE STATISTICS Sales.SalesOrderDetail;
GO

La actualización de estadísticas garantiza que las consultas compilan con estadísticas actualizadas. Sin embargo, actualizar las estadísticas hace que las consultas se recompilen. Por lo tanto puede haber una compensación de rendimiento entre la mejora de los planes de consulta y el tiempo que lleva recompilar las consultas.

Y por ultimo, algo muy importante es hacer backup tambien de las estadísticas, dado que si pasa algo con la base de datos, no solo vamos a querer restaurarla sino tambien que sea usable. Por lo tanto a la hora de hacer backup incluyamos las estadísticas.