“Capas de acceso a datos .NET escalables de verdad contra SQL Server”
Enrique Catalá Bañuls@[email protected]@enriquecatala.com
MAD · NOV 24-25 · 2017
Temario
MAD · NOV 24-25 · 2017
1. Propuesta de problema2. Patrones de acceso a datos3. Objetos4. Concurrencia5. Almacenamiento
Enrique Catalá Bañuls
▪ Ingeniero Informático
▪ Microsoft Data Platform MVP
▪ Mentor en SolidQ
▪ Tuning y alta disponibilidad
[email protected] www.solidq.com
@enriquecatala www.enriquecatala.com
Enrique Catala - [email protected] - @enriquecatala
Mínimo
coste
Datos IoT
masivos en
formato
propietario
Procesamiento
complejo
previo
historificado
Historificado
no
dependiente
del nº de
eventos
Explotación de
datos
simultanea
¿De qué va esta
sesión?
Enrique Catala - [email protected] - @enriquecatala
Mínimo
coste
Datos IoT
masivos en
formato
propietario
Procesamiento
complejo previo
historificado
Historificado no
dependiente del
nº de eventos
Explotación de
datos
simultanea
Problema a solucionar: Planteamientos
•C# y SQL Server
¿Tecnología a utilizar?
•Elijamos
¿Patron de acceso a datos?
•Patrones
Concurrencia
•Elijamos
¿Modelo de almacenamiento?
Tipología de
acceso
Por conjuntos Por cursores
Patrones de
bajo nivel
Dinámico
Adhoc
Parametrizable
Estático
Stored
procedures
Arquitecturas
Modelo
conectividad
Conectada
Desconectada
Modelo de
desarrollo
Manual
ORM
Generalmente es preferible hacer menos operaciones a la BBDD con mas conjuntos de filas
List<T>
O(n)
Dictionary<T,U>
O(1)
System.Collections.Concurrent
Proteje acceso a variables
Utiliza patrones como ReaderWriterLockSlim
Evita lock(this)
No dejes hilos
huerfanos
Concurrency Visualizerfor VS
Consideraciones concurrencia
Enrique Catala - [email protected] - @enriquecatala
public void MethodWithLock(){
lock (syncLock){
// código monothread}
}
ESTO NO SE HACE!
Consideraciones concurrencia
Enrique Catala - [email protected] - @enriquecatala
Patrón multiples lectores, un escritor
Consideraciones concurrencia
public class MultipleReadsOneWriter{
private volatile int value;private ReaderWriterLockSlim rwls;
public MultipleReadsOneWriter(){
rwls = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);}
Enrique Catala - [email protected] - @enriquecatala
Bloqueo ligero para lectores
Consideraciones concurrencia
public int ReadValue(){
int result = default(int);rwls.EnterReadLock();try{
result = value;}finally{
rwls.ExitReadLock();}return result;
}
Enrique Catala - [email protected] - @enriquecatala
Bloqueo duro para escritores
Consideraciones concurrencia
public void WriteValue(int number){
rwls.EnterWriteLock();try{
value = number;}finally{
rwls.ExitWriteLock();}
}
Enrique Catala - [email protected] - @enriquecatala
Tentativa de bloqueo y bloqueo posterior duro
Consideraciones concurrencia
public void WriteValueIfEqual(int compare, int number){
rwls.EnterUpgradeableReadLock();try{
int current = value;if (current == compare){
rwls.EnterWriteLock();try{
value = number;}finally{
rwls.ExitWriteLock();}
}}finally{
rwls.ExitUpgradeableReadLock();}
}
Enrique Catala - [email protected] - @enriquecatala
Lock free
Consideraciones concurrencia
•ConcurrentDictionary
Cargar diccionarios
•Modelo desconectado
•Secuencias
Reserva de IDs•Lectura de datos IoT
• Inserción en
diccionario con ID
asignado en secuencia
Carga de eventos en
Diccionario vacío
•Código multihilo
lockfree
•Cada thread
independiente sobre el
mismo diccionario
Procesado multihilo•BCP directo
Flush a BBDD
Enrique Catala - [email protected] - @enriquecatala
Lock free
Consideraciones concurrencia
Cargar diccionarios
•ConcurrentDictionary
Reserva de IDs
•Modelo desconectado
• Secuencias
Carga de eventos
en Diccionario vacío
•Asignación de IDs
reservados
Procesado multihilo
Flush a BBDD
protected long GetDictionaryKey(String mykey){
try{
long retorno = -1;if (!MyDictionary.TryGetValue(mykey, out retorno)){
GetNextSequenceValuesMyDictionary();}return (retorno);
}catch (Exception){
throw;}
}
EXEC sp_sequence_get_range @sequence_name = N'<sequence>' ,@range_size = range_size ,@range_first_value = range_first_value OUTPUT
Enrique Catala - [email protected] - @enriquecatala
Lock free
Consideraciones concurrencia
Cargar diccionarios
•ConcurrentDictionary
Reserva de IDs
•Modelo desconectado
• Secuencias
Carga de eventos
en Diccionario vacío
•Asignación de IDs
reservados
Procesado multihilo
Flush a BBDD
Parallel.For(0, numeroElementosAProcesar, new ParallelOptions {
MaxDegreeOfParallelism = MAXDOP }, i =>
{try{
Event eventTmp;if (DictionaryToFlush.TryGetValue(i,out eventTmp)){
/// Your complex code goes here///... ... ... ... ... ... ... ... ... ...DictionaryToFlush.TryUpdate(i, eventTmp);
}}catch (Exception e){
exceptions.Enqueue(e);}
});
Enrique Catala - [email protected] - @enriquecatala
Lock free
Consideraciones concurrencia
Cargar diccionarios
•ConcurrentDictionary
Reserva de IDs
•Modelo desconectado
• Secuencias
Carga de eventos
en Diccionario vacío
•Asignación de IDs
reservados
Procesado multihilo
Flush a BBDD
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(cn2)){
bulkCopy.BulkCopyTimeout = 0;
bulkCopy.ColumnMappings.Add(“key", “key");bulkCopy.ColumnMappings.Add(“Value", “value");
///Libreria FastMember (NuGet) para convertir al vuelo///using (var reader =
ObjectReader.Create(cdNew.Values, “key", “Value")){
bulkCopy.DestinationTableName = “YourTable";bulkCopy.WriteToServer(reader);
}}
Enrique Catala - [email protected] - @enriquecatala
Almacenamiento columnar
Grandes volúmenes de datos
• Bloques mínimos de 1M filas
Elevada compression
Lectura minima de datos
Optimiza cache L2
Enrique Catala - [email protected] - @enriquecatala
Almacenamiento in-memory
Otro motor relacional
Máximo
rendimiento
Compatibilidad
Lock free
Tipología de
acceso
Por conjuntos Por cursores
Patrones de
bajo nivel
Dinámico
Adhoc
Parametrizable
Estático
Stored
procedures
Arquitecturas
Modelo
conectividad
Conectada
Desconectada
Modelo de
desarrollo
Manual
ORM
Enrique Catala - [email protected] - @enriquecatala
DEMO: TSQL Query Analytics
DW rendimiento queries
Alertas proactivas
PowerBI para análisis a cualquier nivel
PaaS
http://www.solidq.com/es/tsql-query-analytics/
• Evita procesados fila a filaCapas de acceso a
datos
• La estructura de datos importa, no es todo BBDDComplejidad
algorítmica
• Ya no estamos en los 90. Hasta tu móvil tiene 8
núcleos ☺
Consideraciones de
concurrencia
• Elige con criterio y úsalo bienORMs
• Un motor relacional no son solo tablas,
aprovecha la tecnología eficientemente.Almacenamiento
Top Related