En esta sesión aprenderemos a detectar e implementar correctamente capas de acceso a datos .NET que escalen a las capacidades HW de la máquina
¿Qué aprende nuestro público? Sacar provecho de todas las posibilidades de rendimiento que se ofrecen combinando SQL Server y .NET
Tecnología vista en esta ponencia T-SQL, C#, multihilo,…
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Capas de acceso a datos .net escalables de verdad contra SQL Server
1. “Capas de acceso a datos .NET
escalables de verdad contra SQL
Server”
Enrique Catalá Bañuls
@enriquecatala
ecatala@solidq.com
enrique@enriquecatala.com
MAD · NOV 24-25 · 2017
2. Temario
MAD · NOV 24-25 · 2017
1. Propuesta de problema
2. Patrones de acceso a datos
3. Objetos
4. Concurrencia
5. Almacenamiento
3. Enrique Catalá Bañuls
▪ Ingeniero Informático
▪ Microsoft Data Platform MVP
▪ Mentor en SolidQ
▪ Tuning y alta disponibilidad
ecatala@solidq.com www.solidq.com
@enriquecatala www.enriquecatala.com
4. Enrique Catala - ecatala@solidq.com - @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?
5. Enrique Catala - ecatala@solidq.com - @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?
6. 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
12. System.Collections.Concurrent
Proteje acceso a variables
Utiliza patrones como
ReaderWriterLockSlim
Evita lock(this)
No dejes
hilos
huerfanos
Concurrency Visualizer
for VS
Consideraciones concurrencia
13. Enrique Catala - ecatala@solidq.com - @enriquecatala
public void MethodWithLock()
{
lock (syncLock)
{
// código monothread
}
}
ESTO NO SE HACE!
Consideraciones concurrencia
14. Enrique Catala - ecatala@solidq.com - @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);
}
15. Enrique Catala - ecatala@solidq.com - @enriquecatala
Bloqueo ligero para lectores
Consideraciones concurrencia
public int ReadValue()
{
int result = default(int);
rwls.EnterReadLock();
try
{
result = value;
}
finally
{
rwls.ExitReadLock();
}
return result;
}
16. Enrique Catala - ecatala@solidq.com - @enriquecatala
Bloqueo duro para escritores
Consideraciones concurrencia
public void WriteValue(int number)
{
rwls.EnterWriteLock();
try
{
value = number;
}
finally
{
rwls.ExitWriteLock();
}
}
17. Enrique Catala - ecatala@solidq.com - @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();
}
}
18. Enrique Catala - ecatala@solidq.com - @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
19. Enrique Catala - ecatala@solidq.com - @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
20. Enrique Catala - ecatala@solidq.com - @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);
}
});
21. Enrique Catala - ecatala@solidq.com - @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);
}
}
22. Enrique Catala - ecatala@solidq.com - @enriquecatala
Almacenamiento columnar
Grandes volúmenes de datos
• Bloques mínimos de 1M filas
Elevada compression
Lectura minima de datos
Optimiza cache L2
23. Enrique Catala - ecatala@solidq.com - @enriquecatala
Almacenamiento in-memory
Otro motor relacional
Máximo
rendimiento
Compatibilidad
Lock free
24. 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
25. Enrique Catala - ecatala@solidq.com - @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/
26. • Evita procesados fila a fila
Capas de acceso a
datos
• La estructura de datos importa, no es todo BBDD
Complejidad
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