SlideShare a Scribd company logo
1 of 105
ORM - The tip of an iceberg
Things you may not know about
SQL if you’re stuck with ORMs
Processing 10 million sales
• 10 million sales in a month
• 10 employees
• Generating report with sum of daily sales grouped
by day in the month
• We’re working with local DB and therefore
ignoring latency.
Processing 10 million sales
public interface ISale
{
Guid Id { get; }
int Amount { get; }
DateTime DateTime { get; }
Guid EmployeeId { get; }
}
Processing 10 million sales – generating
var sales = Enumerable.Range(1, 10000000)
.Select(n => new Sale
{
Id = Guid.NewGuid(),
Amount = random.Next(10, 100),
DateTime = new DateTime(2018, now.Month,
n % 29, n % 24, n % 60, 0),
EmployeeId = employeesIds[random.Next(0,
employeesIds.Length)]
})
.ToArray();
Processing 10 million sales – processing
var salesGroupedByDay = sales
.Where(s => s.EmployeeId ==
employeedId)
.GroupBy(s => s.DateTime.Date)
.ToDictionary(
g => g.Key,
g => g.Select(s=>s.Amount).Sum());
Processing 10 million sales – in memory
• Generating sales: ~2,8s (irrelevant)
• Processing elements: ~0,25s
• Total: ~3,05s
Processing 10 million sales – table
CREATE TABLE [dbo].[RawSales]
(
[Id] uniqueidentifier NOT NULL
[Amount] int NOT NULL,
[DateTime] datetime NOT NULL,
[EmployeeId] uniqueidentifier NOT NULL
)
Processing 10 million sales – fetching entire table
var sales = dbContext.Sales
.ToList();
Processing 10 million sales – fetched entire table
• Fetching records: ~88,5s
• Processing elements: ~0,5s
• Total: ~89s
Processing 10 million sales – AsNoTracking()
var sales = dbContext.Sales
.AsNoTracking()
.ToList();
Processing 10 million sales – AsNoTracking()
• Fetching records: ~20,7s
• Processing elements: ~0,25s
• Total: ~20,95s
Processing 10 million sales – filtering on DB side
var sales = dbContext.Sales
.AsNoTracking()
.Where(s=>s.EmployeeId == employeeId)
.ToList();
Processing 10 million sales – Where on DB side
• Fetching records: ~1,5s
• Processing elements: ~0,1s
• Total: ~1,6s
Processing 10 million sales – just columns we
need
var sales = dbContext.Sales
.AsNoTracking()
.Where(s=>s.EmployeeId == employeeId)
.Select(s => new
{
s.DateTime,
s.Amount
})
.ToList();
Processing 10 million sales – just columns we
need
• Fetching records: ~650ms
• Processing elements: ~90ms
• Total: ~740ms
Processing 10 million sales – aggregating in DB
var sales = dbContext.Sales
.AsNoTracking()
//Filtering and projection
.GroupBy(s => s.DateTime.Date)
.ToDictionary(g => g.Key,
g => g.Select(s => s.Amount).Sum())
NotSupportedException!
var sales = dbContext.Sales
.AsNoTracking()
//Filtering and projection
.GroupBy(s => s.DateTime.Date)
.ToDictionary(g => g.Key,
g => g.Select(s => s.Amount).Sum())
Processing 10 million sales – raw SQL
SELECT
CONVERT(date, [DateTime]) AS
SalesDate,
SUM([Amount]) AS AmountSum
FROM [dbo].[RawSales]
WHERE [EmployeeId] = @employeeId
GROUP BY CONVERT(date, [DateTime])
ORDER BY [SalesDate]
Processing 10 million sales – raw SQL
• Entire report: ~600ms
Processing 10 million sales – add persisted
computed column
ALTER TABLE [dbo].[Sales]
ADD [Date] AS
CONVERT(date, [DateTime])
PERSISTED NOT NULL
Processing 10 million sales – add index
CREATE NONCLUSTERED INDEX
[Ix_SalesReport]
ON [dbo].[Sales]
([EmployeeId])
INCLUDE ([Amount], [Date])
Processing 10 million sales – after optimizations
• Entire report: ~180ms
Can we go faster?
Processing 10 million sales – creating view
CREATE VIEW [dbo].[Vw_SalesReport]
WITH SCHEMABINDING
AS
(SELECT
[Date] AS SalesDate,
SUM([Amount]) AS AmountSum,
[EmployeeId],
COUNT_BIG(*) AS RequiredCount
FROM [dbo].[Sales]
GROUP BY [Date], [EmployeeId] )
Processing 10 million sales – indexing view
CREATE UNIQUE CLUSTERED INDEX
[Ix_SalesReportView]
ON [dbo].[Vw_SalesReport]
([EmployeeId], [SalesDate] DESC)
Processing 10 million sales – indexed views result
• Entire report: ~30-40ms
Processing 10 million sales – indexed views result
• Entire report: ~30-40ms – on the first run
• Entire report: ~1-5ms – on the consecutive runs
Reminder – I’m ignoring latency!
Beautiful lies
• View with clustered index is “materialized” and
stored on disk just like a table
• I’ve queried against 280 rows instead of 10
million
•But … still got exactly the same report!
PS. Don’t create indexed views without knowing
the price!
Rafał Hryniewski
@r_hryniewskifb.me/hryniewskinet
ORM - The tip of an iceberg
Things you may not know about
SQL if you’re stuck with ORMs
Agenda
• Introduction
• About me
• Glossary
• Why do we use ORMs?
• Some New SQL Server Features - Dynamic Data Masking, Row
Level Security, Temporal Tables
• Other things you’re missing if you’re stuck with ORMs
• Summary and resources
• Q&A
Glossary
• ORM – Object Relation Mapping
• Micro ORM – lightweight ORM (less options, less performance
overhead)
• DAL – Data Access Layer
• RDBMS – Relational Database Management System
• SSMS – SQL Server Management Studio
Why we’re using ORMs?
• Easier and faster development of DAL
• Lower entry threshold to work with databases
• You can think about your data in object oriented way
• You don’t even need to know SQL at all!
You don’t even need to know SQL!
Short Summary
• You can completely ignore your database
• You can create DAL blazingly fast
• You can watch it goes to hell when your project is mature
enough to produce big amount of data.
Why we’re using ORMs (seriously)?
• They handle non-complex cases well enough
• Development time is expensive…
• … and we can rewrite problematic queries some time later
• Not every query requires polishing and perfecting
• Not everyone is supposed to be SQL experts
• They’re easy and they work (usually)
When should we consider other options?
• When performance is critical
• When it’s much easier to write raw SQL than complicated LINQ
• When we’re encountering performance problems related to DAL
and bloating of DB
• When we need/want to use some advanced database features
So, ORMs are bad?
Sometimes you need a chainsaw,
sometimes you need a scalpel
New Stuff in SQL Server 2016+ and
Azure SQL
Dynamic data masking
Data we could want to mask
• Credit card numbers – XXXX-XXXX-XXXX-1234
• Emails - rXXXX@XXXXXXXXXi.net
• Dates - 1900-01-01
• Personal information - Rafał H.
When to use Dynamic Data Masking?
• When confidential data shouldn’t accidentally leave database
(but it’s not bulletproof!)
• When we’re already using database logins and users for
managing data access policy
Creating column with DDM
CREATE TABLE [dbo].[DDM]
(
[Email] nvarchar(256)
MASKED WITH (FUNCTION = 'email()') NOT NULL
[CredicCard] nvarchar(20)
MASKED WITH ( FUNCTION =
'partial(0,"XXXX-XXXX-XXXX-",4)') NOT NULL
)
Masking types
• Default – depends on masked type
• Random – random number instead of value
• Email – rXXXX@XXXX.com
• Custom – our own pattern
Masked/Unmasked
Granting/Revoking UNMASK permission to user
GRANT UNMASK TO SQLUserName;
REVOKE UNMASK TO SQLUserName;
Querying masked data
• All queries, inserts, deletes and updates will work normally
• Only results are masked and not modified in any way
• DDM is not ultimate security feature, because you can write
queries as usual it’s possible to brute force enough data to
figure out any masked value.
How to use DDM in Entity Framework?
Remember those in connection strings?
"data source=DBADDRESS.database.windows.net;initial
catalog=testdb;persist security info=True;user
id=YOURUSERLOGIN;password=YOURPASSWORD;MultipleAc
tiveResultSets=True"
Row Level Security
Row Level Security
• Limiting access to data on row level
• Handled by Table Valued Function
• Most of the time it’s used with SQL Session and/or logged in
user
Row Level Security – when to use?
• One-database multi-tenant solutions
• One column with value that can be used in filter ie. “TenantId”
• When there is value that you’ll always filter against and if
someone will forget about this predicate, it could result in
leaking data ie. “TenantId”
Row Level Security – how to?
Row Level Security – identify column
CREATE TABLE [dbo].[Employees]
(
[Id] bigint IDENTITY(1,1) NOT NULL,
[CompanyId] bigint NOT NULL,
[FirstName] nvarchar(200) NOT NULL,
[LastName] nvarchar(200) NOT NULL,
[Email] nvarchar(260)
);
Row Level Security – create function
CREATE FUNCTION [sec].[FN_Predicate](@CompanyId
bigint)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
SELECT 1 AS Result
WHERE
CAST(SESSION_CONTEXT(N'CompanyId') AS int) =
@CompanyId;
Row Level Security– attach security policy
CREATE SECURITY POLICY [sec].[Filter]
ADD FILTER PREDICATE [sec].[FN_Predicate](CompanyId)
ON [dbo].[Employees],
ADD BLOCK PREDICATE [sec].[FN_Predicate](CompanyId)
ON [dbo].[Employees] AFTER INSERT,
ADD BLOCK PREDICATE [sec].[FN_Predicate](CompanyId)
ON [dbo].[Employees] BEFORE DELETE,
ADD BLOCK PREDICATE [sec].[FN_Predicate](CompanyId)
ON [dbo].[Employees] BEFORE UPDATE
WITH (STATE = ON);
GO
Row Level Security – querying
SELECT *
FROM [Employees]
SP_SET_SESSION_CONTEXT
@key=N'CompanyId’
,@value=2;
SELECT *
FROM [Employees]
RLS in Entity Framework – setting session in ctor
public EmployeesDbContext(ICompany company) {
companyId = company.Id;
this.Database.Connection.Open(); //Required
SetCompanyIdInSqlSession();
}
private void SetCompanyIdInSqlSession() {
var sqlParameter = new SqlParameter("@companyId",
companyId);
this.Database.ExecuteSqlCommand(
sql: "SP_SET_SESSION_CONTEXT @key=N'CompanyId'
,@value=@companyId",
parameters: sqlParameter);
}
RLS in EF – setting session on connection state
change
public EmployeesDbContext(ICompany company) {
companyId = company.Id;
Database.Connection.StateChange +=
OnConnectionOpened;
}
private void OnConnectionOpened(object sender,
StateChangeEventArgs e) {
if (e.CurrentState == ConnectionState.Open)
SetCompanyIdInSqlSession();
}
Temporal Tables
Temporal Tables
• A.K.A – System Versioned Tables
• Query for state in any point of time
• Query and aggregate state changes for specified time period
• Basically it’s ordinary table backed by table with historical
record with columns indicating time range when it was valid
Temporal Tables – when to use?
• When it’s important to store and/or analyze historical data
• When you need to generate reports based on historical records
• When you want to restore application state for given point in
time easily
• When you want to use ordinary table in usual way, but you want
to gather data about state changes over time just in case
Temporal Tables – creating table in SQL
CREATE TABLE [dbo].[Products]
([Id] uniqueidentifier NOT NULL,
[Name] nvarchar(200) NOT NULL,
[Price] decimal(19,4) NOT NULL,
[Quantity] int NOT NULL,
[StartTime] datetime2 GENERATED ALWAYS AS ROW START
CONSTRAINT [DF_Products_StartTime] DEFAULT SYSUTCDATETIME(),
[EndTime] datetime2 GENERATED ALWAYS AS ROW END
CONSTRAINT [DF_Products_EndTime] DEFAULT CONVERT(datetime2 (0),
'9999-12-31 23:59:59'), PERIOD FOR SYSTEM_TIME ([StartTime], [EndTime]),
CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ([Id]))
WITH
(SYSTEM_VERSIONING = ON
(HISTORY_TABLE = [dbo].[ProductsHistory]));
Temporal Tables – creating table in SQL
CREATE TABLE [dbo].[Products]
(--...
[StartTime] datetime2 GENERATED ALWAYS AS ROW START
CONSTRAINT [DF_Products_StartTime] DEFAULT SYSUTCDATETIME(),
[EndTime] datetime2 GENERATED ALWAYS AS ROW END
CONSTRAINT [DF_Products_EndTime] DEFAULT CONVERT(datetime2
(0), '9999-12-31 23:59:59'),
PERIOD FOR SYSTEM_TIME ([StartTime], [EndTime]))
WITH
(
SYSTEM_VERSIONING = ON
(
HISTORY_TABLE = [dbo].[ProductsHistory]
));
Temporal Tables – Versioned and History Tables
Temporal Tables – Versioned Table (Current State)
SELECT * FROM [dbo].[Products]
Temporal Tables – History Table
SELECT * FROM [dbo].[ProductsHistory]
Temporal tables – state for specific point of time
SELECT [Name], [Price], [Quantity]
FROM [dbo].[Products]
FOR SYSTEM_TIME AS OF '2018-02-28 21:50'
Temporal tables – changes over time range
DECLARE @now datetime2 = getutcdate();
SELECT * FROM [dbo].[Products]
FOR SYSTEM_TIME
BETWEEN '2018-03-01' AND @now
ORDER BY [EndTime] DESC
Temporal tables – aggregation on historical data
SELECT [Name],
MIN([Price]) AS Min_Price, MAX([Price]) AS Max_Price,
MIN([Quantity]) AS Min_Quantity, MAX([Quantity]) AS Max_Quantity
FROM [dbo].[Products]
FOR SYSTEM_TIME
BETWEEN '2018-01-01' AND @now
GROUP BY [Id], [Name]
How to apply this magic in ORM?
You don’t!
Unless you really must. Then:
• Use Micro ORM like Dapper
OR
• For inserts, updates and deletes you should create stored
procedures and map them in Entity Framework.
• For ordrinary queries you can map versioned table or some
kind of view.
• For querying with SYSTEM_TIME you should create and map
your own SQL functions (details in one of my blog posts)
• Usual inserts and updates via ORM won’t work without some
adjustments.
Temporal Tables – tips
• Entity Framework doesn’t work with Temporal Tables without
some adjustments (Time period columns should be mapped
as Store Generated - Computed) and tricky interceptor, to
handle SYSTEM_TIME columns.
• Use raw SQL or create and map procedures, views and/or
functions to interact with versioned tables.
• If you really need ORM – consider using micro ORM (ie.
Dapper), those are more flexible.
• Be careful about table size and set retention period and/or
partition/stretch.
Best tool for working with SQL which you won’t see
in Visual Studio?
Execution Plans
Execution Plans – Interpretting operations and
finding problems
Execution Plans – Fixing problems
CREATE NONCLUSTERED INDEX
AwesomeIndex
ON [SalesLT].[Product]
([ProductCategoryID],
[Color])
INCLUDE ([Name])
Voila!
Notable Mentions – JSON Support (2016+)
• Since MS SQL 2016 it’s possible to operate on JSON with set of
built-in functions like OPENJSON, JSON_VALUE,
JSON_QUERY and JSON_MODIFY.
• Any nvarchar(max) could be used as JSON as long as it
contains valid JSON. You can check it with ISJSON function.
• You can build your own functions, views and procedures around
it and map them in your ORM.
• More details: https://channel9.msdn.com/Shows/Data-
Exposed/SQL-Server-2016-and-JSON-Support
Notable Mentions – Graph Databases (2017+)
• If you really need to build complex and tangled relationships in
your data model you can use limited graph database possibilities
since SQL Server 2017
• Graphs consists of node and edge tables
• It’s still RDBMS so tooling and syntax are not so well-developed as
Neo4J or Gremlin
• More details: https://channel9.msdn.com/Events/Connect/2017/T146
Notable Mentions – Other stuff that you could’ve
missed
• Query Store
• Partitioning
• Stretching database
• Columnstore Indexes
• Transparent Data Encryption
ORM = Faster Development and Limited
Options
Don’t think in object oriented way while working
with database
Most of advanced DB features can be exposed
via views, procedures and functions...
...and those can be mapped in ORMs or used
in raw SQL
Sometimes it’s easier to write raw SQL than use
ORM for the same effect
Programming in SQL is possible (and fun!)
You can use ORM without knowing SQL.
And you can drive a car without license.
It doesn’t mean you should!
You don’t have time to care about performance of
complex queries?
Will you find time when production database will
grow and just start causing problems?
ALWAYS use parameters in raw SQL instead of
putting strings together!
Ever heard about SQL Injection
Should you dive into SQL?
Why should you dive into SQL?
• You will understand it and use it to write better queries even
against ORMs
• You will be able to identify possible performance bottlenecks
early
• You will know when to use chainsaw and when to use scalpel
• It’s a brave new world out there!
Should I stop using ORMs?
Why shouldn’t I stop using ORMs?
• While you can fight for every millisecond it’s often waste of
time
• Most operations should be simple and therefore easily
handled with ORMs
• Most of the time it’s development time that is crucial
• Using raw SQL and ORMs are not mutually exclusive
Resources (from easiest)
• scarydba.com – Grant Fritchey’s Blog (Database Fundamentals cycle)
• app.pluralsight.com/profile/author/joe-sack – Joe Sack on Pluralsight
• Book – “Pro T-SQL Programmer's Guide” Natarajan, J., Bruchez, R.
• Book - “Pro SQL Server Internals” Korotkevitch, D.
Samples and more details on my blog
http://bit.ly/4dev-rh
Questions?
http://bit.ly/4dev-rh
Ask me anything, grab a sticker and try it
yourself!
@r_hryniewskifb.me/hryniewskinet

More Related Content

Similar to ORM - The tip of an iceberg: What SQL developers know that ORMs don't

Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift
Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift
Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift Amazon Web Services Korea
 
How ShopperTrak Is Using MongoDB
How ShopperTrak Is Using MongoDBHow ShopperTrak Is Using MongoDB
How ShopperTrak Is Using MongoDBMongoDB
 
In-memory ColumnStore Index
In-memory ColumnStore IndexIn-memory ColumnStore Index
In-memory ColumnStore IndexSolidQ
 
IOOF IT System Modernisation
IOOF IT System ModernisationIOOF IT System Modernisation
IOOF IT System ModernisationMongoDB
 
Big Data Analytics in the Cloud with Microsoft Azure
Big Data Analytics in the Cloud with Microsoft AzureBig Data Analytics in the Cloud with Microsoft Azure
Big Data Analytics in the Cloud with Microsoft AzureMark Kromer
 
OSDC 2012 | Scaling with MongoDB by Ross Lawley
OSDC 2012 | Scaling with MongoDB by Ross LawleyOSDC 2012 | Scaling with MongoDB by Ross Lawley
OSDC 2012 | Scaling with MongoDB by Ross LawleyNETWAYS
 
Bulletproof Jobs: Patterns For Large-Scale Spark Processing
Bulletproof Jobs: Patterns For Large-Scale Spark ProcessingBulletproof Jobs: Patterns For Large-Scale Spark Processing
Bulletproof Jobs: Patterns For Large-Scale Spark ProcessingSpark Summit
 
AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...
AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...
AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...Amazon Web Services
 
Karen's Favourite Features of SQL Server 2016
Karen's Favourite Features of  SQL Server 2016Karen's Favourite Features of  SQL Server 2016
Karen's Favourite Features of SQL Server 2016Karen Lopez
 
Redis Use Patterns (DevconTLV June 2014)
Redis Use Patterns (DevconTLV June 2014)Redis Use Patterns (DevconTLV June 2014)
Redis Use Patterns (DevconTLV June 2014)Itamar Haber
 
AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...
AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...
AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...Amazon Web Services
 
Scaling MongoDB
Scaling MongoDBScaling MongoDB
Scaling MongoDBMongoDB
 
Mondrian - Geo Mondrian
Mondrian - Geo MondrianMondrian - Geo Mondrian
Mondrian - Geo MondrianSimone Campora
 
AWS Summit Seoul 2015 - AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...
AWS Summit Seoul 2015 -  AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...AWS Summit Seoul 2015 -  AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...
AWS Summit Seoul 2015 - AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...Amazon Web Services Korea
 
OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...
OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...
OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...Altinity Ltd
 
Sql on hadoop the secret presentation.3pptx
Sql on hadoop  the secret presentation.3pptxSql on hadoop  the secret presentation.3pptx
Sql on hadoop the secret presentation.3pptxPaulo Alonso
 
ScaleDB Technical Presentation
ScaleDB Technical PresentationScaleDB Technical Presentation
ScaleDB Technical PresentationIvan Zoratti
 

Similar to ORM - The tip of an iceberg: What SQL developers know that ORMs don't (20)

Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift
Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift
Kengo Horiuchi, SaaS Business Born in the Cloud :: AWS Partner Techshift
 
How ShopperTrak Is Using MongoDB
How ShopperTrak Is Using MongoDBHow ShopperTrak Is Using MongoDB
How ShopperTrak Is Using MongoDB
 
In-memory ColumnStore Index
In-memory ColumnStore IndexIn-memory ColumnStore Index
In-memory ColumnStore Index
 
IOOF IT System Modernisation
IOOF IT System ModernisationIOOF IT System Modernisation
IOOF IT System Modernisation
 
Big Data Analytics in the Cloud with Microsoft Azure
Big Data Analytics in the Cloud with Microsoft AzureBig Data Analytics in the Cloud with Microsoft Azure
Big Data Analytics in the Cloud with Microsoft Azure
 
OSDC 2012 | Scaling with MongoDB by Ross Lawley
OSDC 2012 | Scaling with MongoDB by Ross LawleyOSDC 2012 | Scaling with MongoDB by Ross Lawley
OSDC 2012 | Scaling with MongoDB by Ross Lawley
 
Bulletproof Jobs: Patterns For Large-Scale Spark Processing
Bulletproof Jobs: Patterns For Large-Scale Spark ProcessingBulletproof Jobs: Patterns For Large-Scale Spark Processing
Bulletproof Jobs: Patterns For Large-Scale Spark Processing
 
AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...
AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...
AWS November Webinar Series - Advanced Analytics with Amazon Redshift and the...
 
Super spike
Super spikeSuper spike
Super spike
 
Karen's Favourite Features of SQL Server 2016
Karen's Favourite Features of  SQL Server 2016Karen's Favourite Features of  SQL Server 2016
Karen's Favourite Features of SQL Server 2016
 
Redis Use Patterns (DevconTLV June 2014)
Redis Use Patterns (DevconTLV June 2014)Redis Use Patterns (DevconTLV June 2014)
Redis Use Patterns (DevconTLV June 2014)
 
AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...
AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...
AWS re:Invent 2016: How Fulfillment by Amazon (FBA) and Scopely Improved Resu...
 
Scaling MongoDB
Scaling MongoDBScaling MongoDB
Scaling MongoDB
 
Mondrian - Geo Mondrian
Mondrian - Geo MondrianMondrian - Geo Mondrian
Mondrian - Geo Mondrian
 
AWS DynamoDB and Schema Design
AWS DynamoDB and Schema DesignAWS DynamoDB and Schema Design
AWS DynamoDB and Schema Design
 
AWS Summit Seoul 2015 - AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...
AWS Summit Seoul 2015 -  AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...AWS Summit Seoul 2015 -  AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...
AWS Summit Seoul 2015 - AWS 최신 서비스 살펴보기 - Aurora, Lambda, EFS, Machine Learn...
 
OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...
OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...
OSA Con 2022 - Tips and Tricks to Keep Your Queries under 100ms with ClickHou...
 
Sql on hadoop the secret presentation.3pptx
Sql on hadoop  the secret presentation.3pptxSql on hadoop  the secret presentation.3pptx
Sql on hadoop the secret presentation.3pptx
 
DA_01_Intro.pptx
DA_01_Intro.pptxDA_01_Intro.pptx
DA_01_Intro.pptx
 
ScaleDB Technical Presentation
ScaleDB Technical PresentationScaleDB Technical Presentation
ScaleDB Technical Presentation
 

More from Rafał Hryniewski

DevSecOps - security all the way
DevSecOps - security all the wayDevSecOps - security all the way
DevSecOps - security all the wayRafał Hryniewski
 
DevSecOps - Security all the way
DevSecOps - Security all the wayDevSecOps - Security all the way
DevSecOps - Security all the wayRafał Hryniewski
 
Large scale, distributed and reliable messaging with Kafka
Large scale, distributed and reliable messaging with KafkaLarge scale, distributed and reliable messaging with Kafka
Large scale, distributed and reliable messaging with KafkaRafał Hryniewski
 
Meet Gremlin – your guide through graphs in Cosmos DB
Meet Gremlin – your guide through graphs in Cosmos DBMeet Gremlin – your guide through graphs in Cosmos DB
Meet Gremlin – your guide through graphs in Cosmos DBRafał Hryniewski
 
Shit happens – achieve extensibility, modularity and loosely coupled architec...
Shit happens – achieve extensibility, modularity and loosely coupled architec...Shit happens – achieve extensibility, modularity and loosely coupled architec...
Shit happens – achieve extensibility, modularity and loosely coupled architec...Rafał Hryniewski
 
Public speaking - why am I doing this to myself and why you should too?
Public speaking - why am I doing this to myself and why you should too?Public speaking - why am I doing this to myself and why you should too?
Public speaking - why am I doing this to myself and why you should too?Rafał Hryniewski
 
Azure SQL - more or/and less than SQL Server
Azure SQL - more or/and less than SQL ServerAzure SQL - more or/and less than SQL Server
Azure SQL - more or/and less than SQL ServerRafał Hryniewski
 
Essential security measures in ASP.NET MVC
Essential security measures in ASP.NET MVC Essential security measures in ASP.NET MVC
Essential security measures in ASP.NET MVC Rafał Hryniewski
 
Quick trip around the Cosmos - Things every astronaut supposed to know
Quick trip around the Cosmos - Things every astronaut supposed to knowQuick trip around the Cosmos - Things every astronaut supposed to know
Quick trip around the Cosmos - Things every astronaut supposed to knowRafał Hryniewski
 

More from Rafał Hryniewski (17)

Azure messaging
Azure messagingAzure messaging
Azure messaging
 
Azure developer
Azure developerAzure developer
Azure developer
 
Great webapis
Great webapisGreat webapis
Great webapis
 
DevSecOps - security all the way
DevSecOps - security all the wayDevSecOps - security all the way
DevSecOps - security all the way
 
DevSecOps - Security all the way
DevSecOps - Security all the wayDevSecOps - Security all the way
DevSecOps - Security all the way
 
Anchor modeling
Anchor modelingAnchor modeling
Anchor modeling
 
Large scale, distributed and reliable messaging with Kafka
Large scale, distributed and reliable messaging with KafkaLarge scale, distributed and reliable messaging with Kafka
Large scale, distributed and reliable messaging with Kafka
 
Meet Gremlin – your guide through graphs in Cosmos DB
Meet Gremlin – your guide through graphs in Cosmos DBMeet Gremlin – your guide through graphs in Cosmos DB
Meet Gremlin – your guide through graphs in Cosmos DB
 
Shit happens – achieve extensibility, modularity and loosely coupled architec...
Shit happens – achieve extensibility, modularity and loosely coupled architec...Shit happens – achieve extensibility, modularity and loosely coupled architec...
Shit happens – achieve extensibility, modularity and loosely coupled architec...
 
Web app security essentials
Web app security essentialsWeb app security essentials
Web app security essentials
 
Public speaking - why am I doing this to myself and why you should too?
Public speaking - why am I doing this to myself and why you should too?Public speaking - why am I doing this to myself and why you should too?
Public speaking - why am I doing this to myself and why you should too?
 
Azure SQL - more or/and less than SQL Server
Azure SQL - more or/and less than SQL ServerAzure SQL - more or/and less than SQL Server
Azure SQL - more or/and less than SQL Server
 
Blazor
BlazorBlazor
Blazor
 
Shodan
ShodanShodan
Shodan
 
Essential security measures in ASP.NET MVC
Essential security measures in ASP.NET MVC Essential security measures in ASP.NET MVC
Essential security measures in ASP.NET MVC
 
.NET, Alexa and me
.NET, Alexa and me.NET, Alexa and me
.NET, Alexa and me
 
Quick trip around the Cosmos - Things every astronaut supposed to know
Quick trip around the Cosmos - Things every astronaut supposed to knowQuick trip around the Cosmos - Things every astronaut supposed to know
Quick trip around the Cosmos - Things every astronaut supposed to know
 

Recently uploaded

Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 

Recently uploaded (20)

Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 

ORM - The tip of an iceberg: What SQL developers know that ORMs don't

  • 1.
  • 2. ORM - The tip of an iceberg Things you may not know about SQL if you’re stuck with ORMs
  • 3. Processing 10 million sales • 10 million sales in a month • 10 employees • Generating report with sum of daily sales grouped by day in the month • We’re working with local DB and therefore ignoring latency.
  • 4. Processing 10 million sales public interface ISale { Guid Id { get; } int Amount { get; } DateTime DateTime { get; } Guid EmployeeId { get; } }
  • 5. Processing 10 million sales – generating var sales = Enumerable.Range(1, 10000000) .Select(n => new Sale { Id = Guid.NewGuid(), Amount = random.Next(10, 100), DateTime = new DateTime(2018, now.Month, n % 29, n % 24, n % 60, 0), EmployeeId = employeesIds[random.Next(0, employeesIds.Length)] }) .ToArray();
  • 6. Processing 10 million sales – processing var salesGroupedByDay = sales .Where(s => s.EmployeeId == employeedId) .GroupBy(s => s.DateTime.Date) .ToDictionary( g => g.Key, g => g.Select(s=>s.Amount).Sum());
  • 7. Processing 10 million sales – in memory • Generating sales: ~2,8s (irrelevant) • Processing elements: ~0,25s • Total: ~3,05s
  • 8. Processing 10 million sales – table CREATE TABLE [dbo].[RawSales] ( [Id] uniqueidentifier NOT NULL [Amount] int NOT NULL, [DateTime] datetime NOT NULL, [EmployeeId] uniqueidentifier NOT NULL )
  • 9. Processing 10 million sales – fetching entire table var sales = dbContext.Sales .ToList();
  • 10. Processing 10 million sales – fetched entire table • Fetching records: ~88,5s • Processing elements: ~0,5s • Total: ~89s
  • 11. Processing 10 million sales – AsNoTracking() var sales = dbContext.Sales .AsNoTracking() .ToList();
  • 12. Processing 10 million sales – AsNoTracking() • Fetching records: ~20,7s • Processing elements: ~0,25s • Total: ~20,95s
  • 13. Processing 10 million sales – filtering on DB side var sales = dbContext.Sales .AsNoTracking() .Where(s=>s.EmployeeId == employeeId) .ToList();
  • 14. Processing 10 million sales – Where on DB side • Fetching records: ~1,5s • Processing elements: ~0,1s • Total: ~1,6s
  • 15. Processing 10 million sales – just columns we need var sales = dbContext.Sales .AsNoTracking() .Where(s=>s.EmployeeId == employeeId) .Select(s => new { s.DateTime, s.Amount }) .ToList();
  • 16. Processing 10 million sales – just columns we need • Fetching records: ~650ms • Processing elements: ~90ms • Total: ~740ms
  • 17. Processing 10 million sales – aggregating in DB var sales = dbContext.Sales .AsNoTracking() //Filtering and projection .GroupBy(s => s.DateTime.Date) .ToDictionary(g => g.Key, g => g.Select(s => s.Amount).Sum())
  • 18. NotSupportedException! var sales = dbContext.Sales .AsNoTracking() //Filtering and projection .GroupBy(s => s.DateTime.Date) .ToDictionary(g => g.Key, g => g.Select(s => s.Amount).Sum())
  • 19. Processing 10 million sales – raw SQL SELECT CONVERT(date, [DateTime]) AS SalesDate, SUM([Amount]) AS AmountSum FROM [dbo].[RawSales] WHERE [EmployeeId] = @employeeId GROUP BY CONVERT(date, [DateTime]) ORDER BY [SalesDate]
  • 20. Processing 10 million sales – raw SQL • Entire report: ~600ms
  • 21. Processing 10 million sales – add persisted computed column ALTER TABLE [dbo].[Sales] ADD [Date] AS CONVERT(date, [DateTime]) PERSISTED NOT NULL
  • 22. Processing 10 million sales – add index CREATE NONCLUSTERED INDEX [Ix_SalesReport] ON [dbo].[Sales] ([EmployeeId]) INCLUDE ([Amount], [Date])
  • 23. Processing 10 million sales – after optimizations • Entire report: ~180ms
  • 24. Can we go faster?
  • 25. Processing 10 million sales – creating view CREATE VIEW [dbo].[Vw_SalesReport] WITH SCHEMABINDING AS (SELECT [Date] AS SalesDate, SUM([Amount]) AS AmountSum, [EmployeeId], COUNT_BIG(*) AS RequiredCount FROM [dbo].[Sales] GROUP BY [Date], [EmployeeId] )
  • 26. Processing 10 million sales – indexing view CREATE UNIQUE CLUSTERED INDEX [Ix_SalesReportView] ON [dbo].[Vw_SalesReport] ([EmployeeId], [SalesDate] DESC)
  • 27. Processing 10 million sales – indexed views result • Entire report: ~30-40ms
  • 28. Processing 10 million sales – indexed views result • Entire report: ~30-40ms – on the first run • Entire report: ~1-5ms – on the consecutive runs Reminder – I’m ignoring latency!
  • 29. Beautiful lies • View with clustered index is “materialized” and stored on disk just like a table • I’ve queried against 280 rows instead of 10 million •But … still got exactly the same report! PS. Don’t create indexed views without knowing the price!
  • 31.
  • 32.
  • 33.
  • 34. ORM - The tip of an iceberg Things you may not know about SQL if you’re stuck with ORMs
  • 35. Agenda • Introduction • About me • Glossary • Why do we use ORMs? • Some New SQL Server Features - Dynamic Data Masking, Row Level Security, Temporal Tables • Other things you’re missing if you’re stuck with ORMs • Summary and resources • Q&A
  • 36. Glossary • ORM – Object Relation Mapping • Micro ORM – lightweight ORM (less options, less performance overhead) • DAL – Data Access Layer • RDBMS – Relational Database Management System • SSMS – SQL Server Management Studio
  • 37.
  • 38. Why we’re using ORMs? • Easier and faster development of DAL • Lower entry threshold to work with databases • You can think about your data in object oriented way • You don’t even need to know SQL at all!
  • 39. You don’t even need to know SQL!
  • 40. Short Summary • You can completely ignore your database • You can create DAL blazingly fast • You can watch it goes to hell when your project is mature enough to produce big amount of data.
  • 41. Why we’re using ORMs (seriously)? • They handle non-complex cases well enough • Development time is expensive… • … and we can rewrite problematic queries some time later • Not every query requires polishing and perfecting • Not everyone is supposed to be SQL experts • They’re easy and they work (usually)
  • 42. When should we consider other options? • When performance is critical • When it’s much easier to write raw SQL than complicated LINQ • When we’re encountering performance problems related to DAL and bloating of DB • When we need/want to use some advanced database features
  • 43. So, ORMs are bad?
  • 44. Sometimes you need a chainsaw, sometimes you need a scalpel
  • 45. New Stuff in SQL Server 2016+ and Azure SQL
  • 47. Data we could want to mask • Credit card numbers – XXXX-XXXX-XXXX-1234 • Emails - rXXXX@XXXXXXXXXi.net • Dates - 1900-01-01 • Personal information - Rafał H.
  • 48.
  • 49. When to use Dynamic Data Masking? • When confidential data shouldn’t accidentally leave database (but it’s not bulletproof!) • When we’re already using database logins and users for managing data access policy
  • 50. Creating column with DDM CREATE TABLE [dbo].[DDM] ( [Email] nvarchar(256) MASKED WITH (FUNCTION = 'email()') NOT NULL [CredicCard] nvarchar(20) MASKED WITH ( FUNCTION = 'partial(0,"XXXX-XXXX-XXXX-",4)') NOT NULL )
  • 51. Masking types • Default – depends on masked type • Random – random number instead of value • Email – rXXXX@XXXX.com • Custom – our own pattern
  • 53. Granting/Revoking UNMASK permission to user GRANT UNMASK TO SQLUserName; REVOKE UNMASK TO SQLUserName;
  • 54. Querying masked data • All queries, inserts, deletes and updates will work normally • Only results are masked and not modified in any way • DDM is not ultimate security feature, because you can write queries as usual it’s possible to brute force enough data to figure out any masked value.
  • 55. How to use DDM in Entity Framework?
  • 56. Remember those in connection strings? "data source=DBADDRESS.database.windows.net;initial catalog=testdb;persist security info=True;user id=YOURUSERLOGIN;password=YOURPASSWORD;MultipleAc tiveResultSets=True"
  • 58. Row Level Security • Limiting access to data on row level • Handled by Table Valued Function • Most of the time it’s used with SQL Session and/or logged in user
  • 59. Row Level Security – when to use? • One-database multi-tenant solutions • One column with value that can be used in filter ie. “TenantId” • When there is value that you’ll always filter against and if someone will forget about this predicate, it could result in leaking data ie. “TenantId”
  • 60. Row Level Security – how to?
  • 61. Row Level Security – identify column CREATE TABLE [dbo].[Employees] ( [Id] bigint IDENTITY(1,1) NOT NULL, [CompanyId] bigint NOT NULL, [FirstName] nvarchar(200) NOT NULL, [LastName] nvarchar(200) NOT NULL, [Email] nvarchar(260) );
  • 62. Row Level Security – create function CREATE FUNCTION [sec].[FN_Predicate](@CompanyId bigint) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS Result WHERE CAST(SESSION_CONTEXT(N'CompanyId') AS int) = @CompanyId;
  • 63. Row Level Security– attach security policy CREATE SECURITY POLICY [sec].[Filter] ADD FILTER PREDICATE [sec].[FN_Predicate](CompanyId) ON [dbo].[Employees], ADD BLOCK PREDICATE [sec].[FN_Predicate](CompanyId) ON [dbo].[Employees] AFTER INSERT, ADD BLOCK PREDICATE [sec].[FN_Predicate](CompanyId) ON [dbo].[Employees] BEFORE DELETE, ADD BLOCK PREDICATE [sec].[FN_Predicate](CompanyId) ON [dbo].[Employees] BEFORE UPDATE WITH (STATE = ON); GO
  • 64. Row Level Security – querying SELECT * FROM [Employees] SP_SET_SESSION_CONTEXT @key=N'CompanyId’ ,@value=2; SELECT * FROM [Employees]
  • 65. RLS in Entity Framework – setting session in ctor public EmployeesDbContext(ICompany company) { companyId = company.Id; this.Database.Connection.Open(); //Required SetCompanyIdInSqlSession(); } private void SetCompanyIdInSqlSession() { var sqlParameter = new SqlParameter("@companyId", companyId); this.Database.ExecuteSqlCommand( sql: "SP_SET_SESSION_CONTEXT @key=N'CompanyId' ,@value=@companyId", parameters: sqlParameter); }
  • 66. RLS in EF – setting session on connection state change public EmployeesDbContext(ICompany company) { companyId = company.Id; Database.Connection.StateChange += OnConnectionOpened; } private void OnConnectionOpened(object sender, StateChangeEventArgs e) { if (e.CurrentState == ConnectionState.Open) SetCompanyIdInSqlSession(); }
  • 68. Temporal Tables • A.K.A – System Versioned Tables • Query for state in any point of time • Query and aggregate state changes for specified time period • Basically it’s ordinary table backed by table with historical record with columns indicating time range when it was valid
  • 69. Temporal Tables – when to use? • When it’s important to store and/or analyze historical data • When you need to generate reports based on historical records • When you want to restore application state for given point in time easily • When you want to use ordinary table in usual way, but you want to gather data about state changes over time just in case
  • 70. Temporal Tables – creating table in SQL CREATE TABLE [dbo].[Products] ([Id] uniqueidentifier NOT NULL, [Name] nvarchar(200) NOT NULL, [Price] decimal(19,4) NOT NULL, [Quantity] int NOT NULL, [StartTime] datetime2 GENERATED ALWAYS AS ROW START CONSTRAINT [DF_Products_StartTime] DEFAULT SYSUTCDATETIME(), [EndTime] datetime2 GENERATED ALWAYS AS ROW END CONSTRAINT [DF_Products_EndTime] DEFAULT CONVERT(datetime2 (0), '9999-12-31 23:59:59'), PERIOD FOR SYSTEM_TIME ([StartTime], [EndTime]), CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ([Id])) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ProductsHistory]));
  • 71. Temporal Tables – creating table in SQL CREATE TABLE [dbo].[Products] (--... [StartTime] datetime2 GENERATED ALWAYS AS ROW START CONSTRAINT [DF_Products_StartTime] DEFAULT SYSUTCDATETIME(), [EndTime] datetime2 GENERATED ALWAYS AS ROW END CONSTRAINT [DF_Products_EndTime] DEFAULT CONVERT(datetime2 (0), '9999-12-31 23:59:59'), PERIOD FOR SYSTEM_TIME ([StartTime], [EndTime])) WITH ( SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [dbo].[ProductsHistory] ));
  • 72. Temporal Tables – Versioned and History Tables
  • 73. Temporal Tables – Versioned Table (Current State) SELECT * FROM [dbo].[Products]
  • 74. Temporal Tables – History Table SELECT * FROM [dbo].[ProductsHistory]
  • 75. Temporal tables – state for specific point of time SELECT [Name], [Price], [Quantity] FROM [dbo].[Products] FOR SYSTEM_TIME AS OF '2018-02-28 21:50'
  • 76. Temporal tables – changes over time range DECLARE @now datetime2 = getutcdate(); SELECT * FROM [dbo].[Products] FOR SYSTEM_TIME BETWEEN '2018-03-01' AND @now ORDER BY [EndTime] DESC
  • 77. Temporal tables – aggregation on historical data SELECT [Name], MIN([Price]) AS Min_Price, MAX([Price]) AS Max_Price, MIN([Quantity]) AS Min_Quantity, MAX([Quantity]) AS Max_Quantity FROM [dbo].[Products] FOR SYSTEM_TIME BETWEEN '2018-01-01' AND @now GROUP BY [Id], [Name]
  • 78. How to apply this magic in ORM?
  • 80. Unless you really must. Then: • Use Micro ORM like Dapper OR • For inserts, updates and deletes you should create stored procedures and map them in Entity Framework. • For ordrinary queries you can map versioned table or some kind of view. • For querying with SYSTEM_TIME you should create and map your own SQL functions (details in one of my blog posts) • Usual inserts and updates via ORM won’t work without some adjustments.
  • 81. Temporal Tables – tips • Entity Framework doesn’t work with Temporal Tables without some adjustments (Time period columns should be mapped as Store Generated - Computed) and tricky interceptor, to handle SYSTEM_TIME columns. • Use raw SQL or create and map procedures, views and/or functions to interact with versioned tables. • If you really need ORM – consider using micro ORM (ie. Dapper), those are more flexible. • Be careful about table size and set retention period and/or partition/stretch.
  • 82. Best tool for working with SQL which you won’t see in Visual Studio?
  • 84. Execution Plans – Interpretting operations and finding problems
  • 85. Execution Plans – Fixing problems CREATE NONCLUSTERED INDEX AwesomeIndex ON [SalesLT].[Product] ([ProductCategoryID], [Color]) INCLUDE ([Name])
  • 87. Notable Mentions – JSON Support (2016+) • Since MS SQL 2016 it’s possible to operate on JSON with set of built-in functions like OPENJSON, JSON_VALUE, JSON_QUERY and JSON_MODIFY. • Any nvarchar(max) could be used as JSON as long as it contains valid JSON. You can check it with ISJSON function. • You can build your own functions, views and procedures around it and map them in your ORM. • More details: https://channel9.msdn.com/Shows/Data- Exposed/SQL-Server-2016-and-JSON-Support
  • 88. Notable Mentions – Graph Databases (2017+) • If you really need to build complex and tangled relationships in your data model you can use limited graph database possibilities since SQL Server 2017 • Graphs consists of node and edge tables • It’s still RDBMS so tooling and syntax are not so well-developed as Neo4J or Gremlin • More details: https://channel9.msdn.com/Events/Connect/2017/T146
  • 89. Notable Mentions – Other stuff that you could’ve missed • Query Store • Partitioning • Stretching database • Columnstore Indexes • Transparent Data Encryption
  • 90. ORM = Faster Development and Limited Options
  • 91. Don’t think in object oriented way while working with database
  • 92. Most of advanced DB features can be exposed via views, procedures and functions... ...and those can be mapped in ORMs or used in raw SQL
  • 93. Sometimes it’s easier to write raw SQL than use ORM for the same effect
  • 94. Programming in SQL is possible (and fun!)
  • 95. You can use ORM without knowing SQL. And you can drive a car without license. It doesn’t mean you should!
  • 96. You don’t have time to care about performance of complex queries? Will you find time when production database will grow and just start causing problems?
  • 97. ALWAYS use parameters in raw SQL instead of putting strings together! Ever heard about SQL Injection
  • 98. Should you dive into SQL?
  • 99. Why should you dive into SQL? • You will understand it and use it to write better queries even against ORMs • You will be able to identify possible performance bottlenecks early • You will know when to use chainsaw and when to use scalpel • It’s a brave new world out there!
  • 100. Should I stop using ORMs?
  • 101. Why shouldn’t I stop using ORMs? • While you can fight for every millisecond it’s often waste of time • Most operations should be simple and therefore easily handled with ORMs • Most of the time it’s development time that is crucial • Using raw SQL and ORMs are not mutually exclusive
  • 102. Resources (from easiest) • scarydba.com – Grant Fritchey’s Blog (Database Fundamentals cycle) • app.pluralsight.com/profile/author/joe-sack – Joe Sack on Pluralsight • Book – “Pro T-SQL Programmer's Guide” Natarajan, J., Bruchez, R. • Book - “Pro SQL Server Internals” Korotkevitch, D.
  • 103. Samples and more details on my blog http://bit.ly/4dev-rh
  • 105. Ask me anything, grab a sticker and try it yourself! @r_hryniewskifb.me/hryniewskinet