SlideShare a Scribd company logo
Performance
Considerations –
Dapper .Net
Agenda
• Query Caching
• Buffering
• Query Vs QueryMultiple
• Dirty Tracking
• Q & A
Query Caching
• Dapper caches information about every query it runs, this
allow it to materialize objects quickly and process parameters
quickly.
• The current implementation caches this information in a
ConcurrentDictionary object.
static readonly ConcurrentDictionary<Identity, CacheInfo> _queryCache =
new ConcurrentDictionary<Identity, CacheInfo>();
• The objects it stores are never flushed.
• If you are generating SQL strings on the fly without using
parameters it is possible you will hit memory issues.
• Each query you issue will create an Identity, depending on the
SQL query, its command type and its parameters.
• The CacheInfo object contains IDataReader and IDBCommand
functions and some counters which limit the cached amount.
Cont…
• The Identity class which is used for caching will look like as
mentioned in the below slide,
private Identity(string sql, CommandType? commandType, string connectionString, Type type, Type
parametersType, Type[] otherTypes, int gridIndex)
{
this.sql = sql;
this.commandType = commandType;
this.connectionString = connectionString;
this.type = type;
this.parametersType = parametersType;
this.gridIndex = gridIndex;
unchecked
{
hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this
hashCode = hashCode * 23 + commandType.GetHashCode();
hashCode = hashCode * 23 + gridIndex.GetHashCode();
hashCode = hashCode * 23 + (sql == null ? 0 : sql.GetHashCode());
hashCode = hashCode * 23 + (type == null ? 0 : type.GetHashCode());
if (otherTypes != null)
{
foreach (var t in otherTypes)
{ hashCode = hashCode * 23 + (t == null ? 0 : t.GetHashCode());
}
}
hashCode = hashCode * 23 + (connectionString == null ? 0 : connectionString.GetHashCode());
hashCode = hashCode * 23 + (parametersType == null ? 0 : parametersType.GetHashCode());
}
}
CacheInfo Class
class CacheInfo
{
public Func<IDataReader, object> Deserializer { get; set; }
public Func<IDataReader, object>[] OtherDeserializers { get; set; }
public Action<IDbCommand, object> ParamReader { get; set; }
private int hitCount;
public int GetHitCount() { return Interlocked.CompareExchange(ref hitCount, 0, 0); }
public void RecordHit() { Interlocked.Increment(ref hitCount); }
}
Note on Caching
• Use this
string s = "SELECT email, passwd, login_id, full_name " + "FROM members WHERE " + "email =
@email";
SqlCommand cmd = new SqlCommand(s); cmd.Parameters.Add("@email", email);
• Instead of
cmd.CommandText = "SELECT email, passwd, login_id, full_name " + "FROM members " +
"WHERE email = '" + email + "'";
• The first one is parameterized. It will be cached once. The
second one is not parameterized. It will be cached every time
you write a query like it with a different value for email. This
will explode your memory. (+)
• The first one is vastly superior. It avoids injection attacks.
dapper can cache it once. SQL Server will compile the
execution plan once and cache it. (+)
Buffering
• The buffer is unrelated to cache.
• Dapper does not include any kind of data-cache (although it
does have a cache related to the way how it processes
commands, i.e. "this command string, with this type of
parameter, and this type of entity - has these associated
dynamically generated methods to configure the command
and populate the objects").
• It’s a bool value, supplied against each command object. By
default buffering set to true.
Buffer = true
• In a buffered API all the rows are read before anything is
yielded.
• When dealing with the limited no of rows for example 100 or
200. So that it consumes less memory.
• Once you get the data, the command is complete - so there is
no conflict between that and subsequent operations. (+)
• It doesn’t not hold the active connection for a long time. (+)
• As soon as you get the data, the command has already
released any resources (locks etc), so you're having minimal
impact on the server. (+)
• If the query is immense, loading them all into memory (in a
list) could be expensive / impossible. (-)
• High latency time. (-)
Buffer = false
• If at all dealing with large amount of data (thousands to
millions of rows). It consumes lot of memory for storing the
buffered data.
• you can iterate over immense queries (many millions of rows),
without needing them all in-memory at once - since you're
only ever really looking at the current row being yielded. (+)
• In a streaming API each element is yielded individually. This is
very memory efficient, but if you do lots of subsequent
processing per item, mean that your connection / command
could be "active" for an extended time. (+)
• You don't need to wait for the end of the data to start iterating
- as soon as it has at least one row. (+)
Cont…
• The connection is in-use while you're iterating, which can lead
to "there is already an open reader on the connection" (or
whatever the exact wording is) errors if you try to invoke other
commands on a per-row basis (this can be mitigated by
MARS). (-)
• It holds the active connection for long time, when deals with
large amount of data. (-)
Query Vs QueryMultiple
• We need to choose the right one whether to use Query or
QueryMultiple.
• Its completely based upon the no of resultsets expected from
the command. If expected is more than one resultset we must
use QueryMultiple. If not we must use Query.
• QueryMultiple has some more additional logic. It applies some
amount of complication.
QueryMultiple Example
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
using (var multi = connection.QueryMultiple(sql, new { id = value }))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
}
Dirty Tracking
• Dapper .net provides a nice feature to determine if the update
statement is really required. If the value does not change, it
won’t generate the SQL statement, which is very handy
performance optimization.
• The only requirement is we need to declare a interface for the
object.
Update – Without Tracking
using (var sqlConnection = new
SqlConnection(Constant.DatabaseConnection))
{
sqlConnection.Open();
var entity = sqlConnection.Get(9);
entity.ContactName = "John Smith";
sqlConnection.Update(entity);
var result = sqlConnection.Get(9);
}
Update – With Tracking
public interface ISupplier
{
int Id { get; set; }
string CompanyName { get; set; }
string ContactName { get; set; }
string ContactTitle { get; set; }
}
public class Supplier : ISupplier
{
public int Id { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
public string ContactTitle { get; set; }
}
Cont…
using (var sqlConnection = new SqlConnection(conString))
{
sqlConnection.Open();
var supplier = sqlConnection.Get(9);
Console.WriteLine(string.Format("IsUpdated {0}",
sqlConnection.Update(supplier)));
supplier.CompanyName = “NewManning";
Console.WriteLine(string.Format("IsUpdated {0}",
sqlConnection.Update(supplier)));
}
Q & A

More Related Content

PDF
Image Processing on Delta Lake
PDF
docker.pdf
PPTX
Optional in Java 8
PDF
Spark SQL
PDF
Urbaniser un SI pour 10 ans
PPTX
Apache Calcite overview
PPTX
Stored procedure in sql server
PPTX
Image Processing on Delta Lake
docker.pdf
Optional in Java 8
Spark SQL
Urbaniser un SI pour 10 ans
Apache Calcite overview
Stored procedure in sql server

What's hot (20)

PDF
OrientDB
PDF
How Prometheus Store the Data
PDF
Influxdb and time series data
PDF
Software Testing: Models, Patterns, Tools
PPTX
Date and time functions in mysql
PPTX
SQL Query Optimization: Why Is It So Hard to Get Right?
PDF
Load Testing - How to Stress Your Odoo with Locust
PDF
Celery: The Distributed Task Queue
PDF
A Deeper Understanding of Spark Internals (Hadoop Conference Japan 2014)
PPTX
Time series Analytics - a deep dive into ADX Azure Data Explorer @Data Saturd...
PDF
OrientDB Distributed Architecture v2.0
PDF
Luigi presentation NYC Data Science
PDF
Oracle GoldenGate and Apache Kafka: A Deep Dive Into Real-Time Data Streaming
PPTX
Oracle SQL Tuning for Day-to-Day Data Warehouse Support
PDF
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
PDF
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
PDF
Introduction à ElasticSearch
PPTX
Akka Actor presentation
PDF
PDF
An introduction to MongoDB
OrientDB
How Prometheus Store the Data
Influxdb and time series data
Software Testing: Models, Patterns, Tools
Date and time functions in mysql
SQL Query Optimization: Why Is It So Hard to Get Right?
Load Testing - How to Stress Your Odoo with Locust
Celery: The Distributed Task Queue
A Deeper Understanding of Spark Internals (Hadoop Conference Japan 2014)
Time series Analytics - a deep dive into ADX Azure Data Explorer @Data Saturd...
OrientDB Distributed Architecture v2.0
Luigi presentation NYC Data Science
Oracle GoldenGate and Apache Kafka: A Deep Dive Into Real-Time Data Streaming
Oracle SQL Tuning for Day-to-Day Data Warehouse Support
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Query Optimization with MySQL 5.6: Old and New Tricks - Percona Live London 2013
Introduction à ElasticSearch
Akka Actor presentation
An introduction to MongoDB
Ad

Viewers also liked (11)

PPTX
Dapper - Rise of the MicroORM
PDF
Object Relational Mapping with Dapper (Micro ORM)
PDF
Repository and Unit Of Work Design Patterns
PPTX
Introduction the Repository Pattern
PDF
Dapper & Dapper.SimpleCRUD
PPTX
Dapper + QueryObject
PDF
Real World Dependency Injection - phpday
PDF
Difference between wcf and asp.net web api
PPTX
Dependency injection in asp.net core
PDF
Generic repository pattern with ASP.NET MVC and Entity Framework
PPTX
Real World Asp.Net WebApi Applications
Dapper - Rise of the MicroORM
Object Relational Mapping with Dapper (Micro ORM)
Repository and Unit Of Work Design Patterns
Introduction the Repository Pattern
Dapper & Dapper.SimpleCRUD
Dapper + QueryObject
Real World Dependency Injection - phpday
Difference between wcf and asp.net web api
Dependency injection in asp.net core
Generic repository pattern with ASP.NET MVC and Entity Framework
Real World Asp.Net WebApi Applications
Ad

Similar to Dapper performance (20)

PPTX
Кирилл Безпалый, .NET Developer, Ciklum
PPTX
Developing on SQL Azure
KEY
DjangoCon 2010 Scaling Disqus
PPTX
Scaling asp.net websites to millions of users
PPTX
Orms vs Micro-ORMs
PPTX
Migration to ClickHouse. Practical guide, by Alexander Zaitsev
ODP
Performance Tuning
PPT
Jdbc oracle
PDF
ITB2019 CBStreams : Accelerate your Functional Programming with the power of ...
PDF
CBStreams - Java Streams for ColdFusion (CFML)
PPT
PPTX
Advanced .NET Data Access with Dapper
PPTX
My Database Skills Killed the Server
PPTX
Azure SQL Database - Connectivity Best Practices
PDF
How to use the new Domino Query Language
ODP
Practical catalyst
PPTX
Presentation of OrientDB v2.2 - Webinar
PDF
Spring data requery
PPT
For Beginers - ADO.Net
PDF
What's New in Apache Hive
Кирилл Безпалый, .NET Developer, Ciklum
Developing on SQL Azure
DjangoCon 2010 Scaling Disqus
Scaling asp.net websites to millions of users
Orms vs Micro-ORMs
Migration to ClickHouse. Practical guide, by Alexander Zaitsev
Performance Tuning
Jdbc oracle
ITB2019 CBStreams : Accelerate your Functional Programming with the power of ...
CBStreams - Java Streams for ColdFusion (CFML)
Advanced .NET Data Access with Dapper
My Database Skills Killed the Server
Azure SQL Database - Connectivity Best Practices
How to use the new Domino Query Language
Practical catalyst
Presentation of OrientDB v2.2 - Webinar
Spring data requery
For Beginers - ADO.Net
What's New in Apache Hive

Recently uploaded (20)

PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Approach and Philosophy of On baking technology
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
A comparative analysis of optical character recognition models for extracting...
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
Big Data Technologies - Introduction.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
A Presentation on Artificial Intelligence
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
Digital-Transformation-Roadmap-for-Companies.pptx
SOPHOS-XG Firewall Administrator PPT.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
Approach and Philosophy of On baking technology
The Rise and Fall of 3GPP – Time for a Sabbatical?
A comparative analysis of optical character recognition models for extracting...
Group 1 Presentation -Planning and Decision Making .pptx
Network Security Unit 5.pdf for BCA BBA.
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
MYSQL Presentation for SQL database connectivity
Big Data Technologies - Introduction.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
A Presentation on Artificial Intelligence
Programs and apps: productivity, graphics, security and other tools
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Reach Out and Touch Someone: Haptics and Empathic Computing

Dapper performance

  • 2. Agenda • Query Caching • Buffering • Query Vs QueryMultiple • Dirty Tracking • Q & A
  • 3. Query Caching • Dapper caches information about every query it runs, this allow it to materialize objects quickly and process parameters quickly. • The current implementation caches this information in a ConcurrentDictionary object. static readonly ConcurrentDictionary<Identity, CacheInfo> _queryCache = new ConcurrentDictionary<Identity, CacheInfo>(); • The objects it stores are never flushed. • If you are generating SQL strings on the fly without using parameters it is possible you will hit memory issues. • Each query you issue will create an Identity, depending on the SQL query, its command type and its parameters. • The CacheInfo object contains IDataReader and IDBCommand functions and some counters which limit the cached amount.
  • 4. Cont… • The Identity class which is used for caching will look like as mentioned in the below slide,
  • 5. private Identity(string sql, CommandType? commandType, string connectionString, Type type, Type parametersType, Type[] otherTypes, int gridIndex) { this.sql = sql; this.commandType = commandType; this.connectionString = connectionString; this.type = type; this.parametersType = parametersType; this.gridIndex = gridIndex; unchecked { hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this hashCode = hashCode * 23 + commandType.GetHashCode(); hashCode = hashCode * 23 + gridIndex.GetHashCode(); hashCode = hashCode * 23 + (sql == null ? 0 : sql.GetHashCode()); hashCode = hashCode * 23 + (type == null ? 0 : type.GetHashCode()); if (otherTypes != null) { foreach (var t in otherTypes) { hashCode = hashCode * 23 + (t == null ? 0 : t.GetHashCode()); } } hashCode = hashCode * 23 + (connectionString == null ? 0 : connectionString.GetHashCode()); hashCode = hashCode * 23 + (parametersType == null ? 0 : parametersType.GetHashCode()); } }
  • 6. CacheInfo Class class CacheInfo { public Func<IDataReader, object> Deserializer { get; set; } public Func<IDataReader, object>[] OtherDeserializers { get; set; } public Action<IDbCommand, object> ParamReader { get; set; } private int hitCount; public int GetHitCount() { return Interlocked.CompareExchange(ref hitCount, 0, 0); } public void RecordHit() { Interlocked.Increment(ref hitCount); } }
  • 7. Note on Caching • Use this string s = "SELECT email, passwd, login_id, full_name " + "FROM members WHERE " + "email = @email"; SqlCommand cmd = new SqlCommand(s); cmd.Parameters.Add("@email", email); • Instead of cmd.CommandText = "SELECT email, passwd, login_id, full_name " + "FROM members " + "WHERE email = '" + email + "'"; • The first one is parameterized. It will be cached once. The second one is not parameterized. It will be cached every time you write a query like it with a different value for email. This will explode your memory. (+) • The first one is vastly superior. It avoids injection attacks. dapper can cache it once. SQL Server will compile the execution plan once and cache it. (+)
  • 8. Buffering • The buffer is unrelated to cache. • Dapper does not include any kind of data-cache (although it does have a cache related to the way how it processes commands, i.e. "this command string, with this type of parameter, and this type of entity - has these associated dynamically generated methods to configure the command and populate the objects"). • It’s a bool value, supplied against each command object. By default buffering set to true.
  • 9. Buffer = true • In a buffered API all the rows are read before anything is yielded. • When dealing with the limited no of rows for example 100 or 200. So that it consumes less memory. • Once you get the data, the command is complete - so there is no conflict between that and subsequent operations. (+) • It doesn’t not hold the active connection for a long time. (+) • As soon as you get the data, the command has already released any resources (locks etc), so you're having minimal impact on the server. (+) • If the query is immense, loading them all into memory (in a list) could be expensive / impossible. (-) • High latency time. (-)
  • 10. Buffer = false • If at all dealing with large amount of data (thousands to millions of rows). It consumes lot of memory for storing the buffered data. • you can iterate over immense queries (many millions of rows), without needing them all in-memory at once - since you're only ever really looking at the current row being yielded. (+) • In a streaming API each element is yielded individually. This is very memory efficient, but if you do lots of subsequent processing per item, mean that your connection / command could be "active" for an extended time. (+) • You don't need to wait for the end of the data to start iterating - as soon as it has at least one row. (+)
  • 11. Cont… • The connection is in-use while you're iterating, which can lead to "there is already an open reader on the connection" (or whatever the exact wording is) errors if you try to invoke other commands on a per-row basis (this can be mitigated by MARS). (-) • It holds the active connection for long time, when deals with large amount of data. (-)
  • 12. Query Vs QueryMultiple • We need to choose the right one whether to use Query or QueryMultiple. • Its completely based upon the no of resultsets expected from the command. If expected is more than one resultset we must use QueryMultiple. If not we must use Query. • QueryMultiple has some more additional logic. It applies some amount of complication.
  • 13. QueryMultiple Example var sql = @" select * from Customers where CustomerId = @id select * from Orders where CustomerId = @id select * from Returns where CustomerId = @id"; using (var multi = connection.QueryMultiple(sql, new { id = value })) { var customer = multi.Read<Customer>().Single(); var orders = multi.Read<Order>().ToList(); var returns = multi.Read<Return>().ToList(); }
  • 14. Dirty Tracking • Dapper .net provides a nice feature to determine if the update statement is really required. If the value does not change, it won’t generate the SQL statement, which is very handy performance optimization. • The only requirement is we need to declare a interface for the object.
  • 15. Update – Without Tracking using (var sqlConnection = new SqlConnection(Constant.DatabaseConnection)) { sqlConnection.Open(); var entity = sqlConnection.Get(9); entity.ContactName = "John Smith"; sqlConnection.Update(entity); var result = sqlConnection.Get(9); }
  • 16. Update – With Tracking public interface ISupplier { int Id { get; set; } string CompanyName { get; set; } string ContactName { get; set; } string ContactTitle { get; set; } } public class Supplier : ISupplier { public int Id { get; set; } public string CompanyName { get; set; } public string ContactName { get; set; } public string ContactTitle { get; set; } }
  • 17. Cont… using (var sqlConnection = new SqlConnection(conString)) { sqlConnection.Open(); var supplier = sqlConnection.Get(9); Console.WriteLine(string.Format("IsUpdated {0}", sqlConnection.Update(supplier))); supplier.CompanyName = “NewManning"; Console.WriteLine(string.Format("IsUpdated {0}", sqlConnection.Update(supplier))); }
  • 18. Q & A