SlideShare una empresa de Scribd logo
1 de 60
#SQLSatMadrid
Modelos de datos en
Azure Cosmos DB
Alberto Diaz Martin
@adiazcan
#SQLSatMadrid
ALBERTO DÍAZ
CTIO | Microsoft Azure MVP
ENCAMINA
https://blogs.encamina.com/
@adiazcan
https://www.linkedin.com/in/albertodiazmartin/
Alberto Diaz cuenta con más de 15 años de experiencia en la Industria
IT, todos ellos trabajando con tecnologías Microsoft. Actualmente, es
Chief Technology Innovation Officer en ENCAMINA, liderando el
desarrollo de software con tecnología Microsoft, y miembro del equipo
de Dirección.
Para la comunidad, trabaja como organizador y speaker de las
conferencias más relevantes del mundo Microsoft en España, en las
cuales es uno de los referentes en SharePoint, Office 365 y Azure.
Autor de diversos libros y artículos en revistas profesionales y blogs, en
2013 empezó a formar parte del equipo de Dirección de
CompartiMOSS, una revista digital sobre tecnologías Microsoft.
Desde 2011 ha sido nombrado Microsoft MVP, reconocimiento que ha
renovado por séptimo año consecutivo. Se define como un geek,
amante de los smartphones y desarrollador. Fundador de TenerifeDev
(www.tenerifedev.com), un grupo de usuarios de .NET en Tenerife, y
coordinador de SUGES (Grupo de Usuarios de SharePoint de España,
www.suges.es)
PlatinumGoldSilver
Venue
Global
BIG Thanks to SQLSatMadrid sponsors
Sigue #SQLSatMadrid
Session’s objectives
BETTER UNDERSTAND
MODELING AND
PARTITIONING ON
COSMOS DB
MODEL A REAL-WORLD
EXAMPLE
MAXIMIZE
PERFORMANCE AND
SCALABILITY
APPRECIATE HOW IT
DIFFERS FROM
RELATIONAL MODELING
Sigue #SQLSatMadrid
MongoDB
Table
API
Turnkey global
distribution
Elastic scale out
of storage & throughput
Guaranteed low latency
at the 99th percentile
Comprehensive
SLAs
Five well-defined
consistency models
Azure Cosmos DB
DocumentColumn-family
Key-value Graph
Core
(SQL)
API
Sigue #SQLSatMadrid
Our domain
# 904
Sigue #SQLSatMadrid
Our domain
Users can create posts. Users can also like and add comments to posts.
A front page displays a feed of recently created posts. It is possible to list all posts for a
particular user. It is also possible to list all comments of a post and all users who have liked a
post.
A post is displayed with its author's username and a count of comments and likes. Comments
and likes are also displayed with the username of their authors.
When displayed as lists, posts only present a truncated summary of their content.
Sigue #SQLSatMadrid
Maybe you instantly think about…
# 904
Sigue #SQLSatMadrid
Start by identifying the access patterns
What are the requests that our design will have to serve?
To make it easier to follow, categorize them as:
Command (write request)
Query (read-only request)
# 904
Sigue #SQLSatMadrid
Start by identifying the access patterns
[C1] Create/edit a user's profile
[Q1] Retrieve a user's profile
[C2] Create/edit a post
[Q2] Retrieve a post
[Q3] List a user's posts in short form
[C3] Create a comment
[Q4] List a post's comments
[C4] Like a post
[Q5] List a post's likes
[Q6] List the x most recent posts in short form (feed)
# 904
Sigue #SQLSatMadrid
The rules of the game
# 904
Sigue #SQLSatMadrid
The rules of the game: data model
In a Cosmos DB database, we store documents in collections like rows in a table?
user likepost comment
users likesposts comments
NO
# 904
Sigue #SQLSatMadrid
The rules of the game: data model
In a Cosmos DB database, we store documents in collections
user likepost comment
users posts
# 904
Sigue #SQLSatMadrid
The rules of the game: provisioned performance
Expected performance has to be provisioned
Expressed in Request Units per second (RU/s)
Represents the "cost" of a request in terms of CPU, memory and I/O
Performance can be provisioned:
at the database-level
at the collection-level
Provisioned performance can be changed programmatically with API calls
# 904
Sigue #SQLSatMadrid
The rules of the game: partitioning
Cosmos DB achieves horizontal scalability by partitioning your data
# 904
Sigue #SQLSatMadrid
The rules of the game: partitioning
Cosmos DB achieves horizontal scalability by partitioning your data
logical partitions
Logical partitions group your data according to the collection's partition key
'userId': 'abc' 'userId': 'def' 'userId': 'ghi'
# 904
Sigue #SQLSatMadrid
The rules of the game: partitioning
A good partition key ensures well-balanced partitions
Both in terms of storage and in terms of throughput
Ideally, read queries should get all their results from one partition
'userId': 'abc' 'userId': 'def' 'userId': 'ghi'
SELECT * FROM u WHERE u.userId = 'def'
Sigue #SQLSatMadrid
V1: a first shot
{
"id": "<user-id>",
"username": "<user-username>"
}
{
"id": "<post-id>",
"userId": "<post-author-id>",
"title": "<post-title>",
"content": "<post-content>",
"creationDate": "<post-creation-date>"
}
{
"id": "<comment-id>",
"postId": "<post-id>",
"userId": "<comment-author-id>",
"content": "<comment-content>",
"creationDate": "<comment-creation-date>"
}
{
"id": "<like-id>",
"postId": "<post-id>",
"userId": "<liker-id>",
"creationDate": "<like-creation-date>"
}
Sigue #SQLSatMadrid
To embed or to reference?
{
"id": "…",
"relatedItemId": "<related-item-id>"
}
{
"id": "<related-item-id>",
"relatedData": "…"
}
{
"id": "…",
"relatedItem": {
"relatedData": "…"
}
}
Sigue #SQLSatMadrid
To embed or to reference?
Embed when:
1:1
1:few
Items queried together
Items updated together
Reference when:
1:many (unbounded)
Many:many
Items updated independently
Sigue #SQLSatMadrid
V1: a first shot
{
"id": "<user-id>",
"username": "<user-username>"
}
users
PK: id
posts
PK: postId
{
"id": "<post-id>",
"type": "post",
"postId": "<post-id>",
"userId": "<post-author-id>",
"title": "<post-title>",
"content": "<post-content>",
"creationDate": "<post-creation-date>"
}
{
"id": "<comment-id>",
"type": "comment",
"postId": "<post-id>",
"userId": "<comment-author-id>",
"content": "<comment-content>",
"creationDate": "<comment-creation-date>"
}
{
"id": "<like-id>",
"type": "like",
"postId": "<post-id>",
"userId": "<liker-id>",
"creationDate": "<like-creation-date>"
}
# 904
Sigue #SQLSatMadrid
How well does our model perform?
Benchmarked against a dummy dataset
100,000 users
5 – 50 posts / user
0 – 25 comments / post
0 – 100 likes / post
users posts
100k docs 95+M docs
100 GB
Sigue #SQLSatMadrid
Create/edit a user’s profile
C1
users
PK: id
posts
PK: postId
7 ms / 5.71 RU
Sigue #SQLSatMadrid
Retrieve a user's profile
Q1
users
PK: id
posts
PK: postId
SELECT * FROM u WHERE u.id = '<user-id>'
3 ms / 2.90 RU
Sigue #SQLSatMadrid
Create/edit a post
C2
users
PK: id
posts
PK: postId
Sigue #SQLSatMadrid
Retrieve a post
Q2
users
PK: id
posts
PK: postId
SELECT * FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'post'
SELECT u.username FROM u
WHERE u.id = '<post-author-id>'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like' 9 ms / 19.54 RU
Sigue #SQLSatMadrid
List a user's posts in short form
Q3
users
PK: id
posts
SELECT * FROM p
WHERE p.userId = '<author-id>'
AND p.type = 'post'
SELECT u.username FROM u
WHERE u.id = '<post-author-id>'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like'
PK: postId
130 ms / 619.41 RU
Sigue #SQLSatMadrid
Create a comment
C3
users
PK: id
posts
PK: postId
Sigue #SQLSatMadrid
List a post's comments
Q4
users
PK: id
posts
PK: postId
SELECT * FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT u.username FROM u
WHERE u.id = '<comment-author-id>'
23 ms / 27.72 RU
Sigue #SQLSatMadrid
Like a post
C4
users
PK: id
posts
PK: postId
Sigue #SQLSatMadrid
List a post's likes
Q5
users
PK: id
posts
PK: postId
SELECT * FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like'
SELECT u.username FROM u
WHERE u.id = '<liker-id>'
Sigue #SQLSatMadrid
List the x most recent posts in short form (feed)
Q6
users
PK: id
posts
PK: postId
SELECT TOP <x> * FROM p
WHERE p.type = 'post'
ORDER BY p.creationDate DESC
SELECT u.username FROM u
WHERE u.id = '<post-author-id>'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like' 306 ms / 2063.54 RU
# 904
Sigue #SQLSatMadrid
V1: performance issues
Having to issue multiple queries to handle a single request
Issuing queries that don't filter on the partition key, leading to a
partition scan
Sigue #SQLSatMadrid
Retrieve a post
Q2
users
PK: id
posts
PK: postId
SELECT * FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'post'
SELECT u.username FROM u
WHERE u.id = '<post-author-id>'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like'
Sigue #SQLSatMadrid
V2: introducing denormalization
users
PK: id
posts
PK: postId
{
"id": "<post-id>",
"type": "post",
"postId": "<post-id>",
"userId": "<post-author-id>",
"userUsername": "<post-author-
username>",
"title": "<post-title>",
"content": "<post-content>",
"commentCount": <number-of-comments>,
"likeCount": <number-of-likes>,
"creationDate": "<post-creation-date>"
}
{
"id": "<comment-id>",
"type": "comment",
"postId": "<post-id>",
"userId": "<comment-author-id>",
"userUsername": "<comment-author-username>",
"content": "<comment-content>",
"creationDate": "<comment-creation-date>"
}
{
"id": "<like-id>",
"type": "like",
"postId": "<post-id>",
"userId": "<liker-id>",
"userUsername": "<liker-username>",
"creationDate": "<like-creation-date>"
}
# 904
Sigue #SQLSatMadrid
Denormalizing within the same logical partition
with stored procedures
Written in Javascript
Scoped to a single logical partition
Executed as atomic transactions
Sigue #SQLSatMadrid
Create a comment
C3
users
PK: id
posts
PK: postId
function createComment(postId, comment) {
var collection = getContext().getCollection();
collection.readDocument(
`${collection.getAltLink()}/docs/${postId}`,
function (err, post) {
post.commentCount++;
collection.replaceDocument(
post._self,
post,
function (err) {
comment.postId = postId;
collection.createDocument(
collection.getSelfLink(),
comment
);
}
);
});
}
Sigue #SQLSatMadrid
Denormalizing across logical partitions and
containers with the change feed
Sigue #SQLSatMadrid
Denormalizing usernames into posts
function updateUsername(userId, username) {
var collection = getContext().getCollection();
collection.queryDocuments(
collection.getSelfLink(),
`SELECT * FROM p WHERE p.userId =
'${userId}'`,
function (err, results) {
for (var i in results) {
var doc = results[i];
doc.userUsername = username;
collection.replaceDocument(
collection.getSelfLink(),
doc);
}
});
}
Sigue #SQLSatMadrid
Retrieve a post
Q2
users
PK: id
posts
PK: postId
SELECT * FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'post'
SELECT u.username FROM u
WHERE u.id = '<post-author-id>'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like' 3 ms / 5.40 RU
Sigue #SQLSatMadrid
List a post's comments
Q4
users
PK: id
posts
PK: postId
SELECT * FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT u.username FROM u
WHERE u.id = '<comment-author-id>'
Q4
4 ms / 7.72 RU
Sigue #SQLSatMadrid
List a post's likes
Q5
users
PK: id
posts
PK: postId
SELECT * FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like'
SELECT u.username FROM u
WHERE u.id = '<liker-id>'
Q5
Sigue #SQLSatMadrid
List a user's posts in short form
Q3
users
PK: id
posts
SELECT * FROM p
WHERE p.userId = '<author-id>'
AND p.type = 'post'
SELECT u.username FROM u
WHERE u.id = '<post-author-id>'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like'
PK: postId
Sigue #SQLSatMadrid
V3: denormalizing entire documents
users
PK: id
posts
PK: postId
Sigue #SQLSatMadrid
V3: denormalizing entire documents
users
PK: id
posts
PK: postId
{
"id": "<post-id>",
"type": "post",
"userId": "<post-author-id>",
"userUsername": "<post-author-
username>",
"title": "<post-title>",
"content": "<post-content>",
"commentCount": <number-of-comments>,
"likeCount": <number-of-likes>,
"creationDate": "<post-creation-date>"
}
PK: userId
{
"id": "<user-id>",
"type": "user",
"userId": "<user-id>",
"username": "<user-username>"
}
Sigue #SQLSatMadrid
Denormalizing documents with the change feed
posts
users
truncate content
if (type == 'post')
Sigue #SQLSatMadrid
PK: userId
List a user's posts in short form
Q3
users
posts
SELECT * FROM p
WHERE p.userId = '<author-id>'
AND p.type = 'post'
PK: postId
4 ms / 6.46 RU
Sigue #SQLSatMadrid
List the x most recent posts in short form (feed)
Q6
users
PK: id
posts
PK: postId
SELECT TOP <x> * FROM p
WHERE p.type = 'post'
ORDER BY p.creationDate DESC
SELECT u.username FROM u
WHERE u.id = '<post-author-id>'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'comment'
SELECT COUNT(1) FROM p
WHERE p.postId = '<post-id>'
AND p.type = 'like'
Sigue #SQLSatMadrid
V3: denormalizing entire documents
users
posts
PK: postId
PK: userId
Sigue #SQLSatMadrid
V3: denormalizing entire documents
users
posts
PK: postId
PK: userId
{
"id": "<post-id>",
"type": "post",
"userId": "<post-author-id>",
"userUsername": "<post-author-
username>",
"title": "<post-title>",
"content": "<post-content>",
"commentCount": <number-of-comments>,
"likeCount": <number-of-likes>,
"creationDate": "<post-creation-date>"
}
feed
PK: type
Sigue #SQLSatMadrid
Denormalizing documents with the change feed
posts
users
truncate
content
if (type == 'post')
Sigue #SQLSatMadrid
Denormalizing documents with the change feed
posts
users
truncate content
if (type == 'post')
feed
post-trigger:
truncate container
Sigue #SQLSatMadrid
List the x most recent posts in short form (feed)
Q6
users
PK: id
posts
PK: postId
SELECT TOP <x> * FROM p
WHERE p.type = 'post'
ORDER BY p.creationDate DESC
feed
PK: type9 ms / 16.97 RU
Sigue #SQLSatMadrid
Our final design
users posts feed
user
post
post
post
like
comment
Sigue #SQLSatMadrid
Our final design
users posts feed
if (type == 'user')
truncate content
if (type == 'post')
updateUsername()
# 904
Sigue #SQLSatMadrid
Denormalization can be added later
V1 was not that bad!
You can add denormalization later
The change feed is persistent
Run a one-time catch-up operation
Monitor your database performance and setup alerts
V1
C1 7 ms / 5.71 RU
Q1 3 ms / 2.90 RU
C2 9 ms / 8.76 RU
Q2 9 ms / 19.54 RU
Q3 130 ms / 619.41
RU
C3 7 ms / 8.57 RU
Q4 23 ms / 27.72 RU
C4 6 ms / 7.05 RU
Q5 59 ms / 58.92 RU
Q6 306 ms / 2063.54
RU
# 904
Sigue #SQLSatMadrid
An overall look at performance
V1
C1 7 ms / 5.71 RU
Q1 3 ms / 2.90 RU
C2 9 ms / 8.76 RU
Q2 9 ms / 19.54 RU
Q3 130 ms / 619.41
RU
C3 7 ms / 8.57 RU
Q4 23 ms / 27.72 RU
C4 6 ms / 7.05 RU
Q5 59 ms / 58.92 RU
Q6 306 ms / 2063.54
RU
V2 V3
7 ms / 5.71 RU 7 ms / 5.71 RU
3 ms / 2.90 RU 3 ms / 2.90 RU
9 ms / 8.76 RU 9 ms / 8.76 RU
3 ms / 5.11 RU 3 ms / 5.11 RU
28 ms / 201.54
RU
4 ms / 6.46 RU
7 ms / 15.27 RU 7 ms / 15.27 RU
4 ms / 7.72 RU 4 ms / 7.72 RU
7 ms / 14.67 RU 7 ms / 14.67 RU
4 ms / 8.92 RU 4 ms / 8.92 RU
83 ms / 532.33
RU
9 ms / 16.97 RU
# 904
Sigue #SQLSatMadrid
What about the cost of denormalization?
We optimized for a read-heavy scenario
Reads >> writes
Q6 went from 2,000+ to 17 RUs (120x optimization)
Saved 1920 RUs by denormalizing posts at ~10RUs / document
All depends on your specific scenario and access patterns
# 904
Sigue #SQLSatMadrid
Most importantly: what’s our scalability?
V3: limitless!
Performance will not depend on
number of documents
number of users
number of posts
Whether you have 10 or 10M users, query latency
will always be the same
V3
C1 7 ms / 5.71 RU
Q1 3 ms / 2.90 RU
C2 9 ms / 8.76 RU
Q2 3 ms / 5.11 RU
Q3 4 ms / 6.46 RU
C3 7 ms / 14.67 RU
Q4 4 ms / 7.72 RU
C4 7 ms / 14.67 RU
Q5 4 ms / 8.92 RU
Q6 9 ms / 16.97 RU
# 904
Sigue #SQLSatMadrid
Take away
Don’t think as relational database
Iterate your model and denormalize
Create aggregatea and materialize views
Denormalize

Más contenido relacionado

Similar a SQL Saturday Madrid 2019 - Data model with Azure Cosmos DB

Write better code faster with rest data contracts api strat
Write better code faster with rest data contracts   api stratWrite better code faster with rest data contracts   api strat
Write better code faster with rest data contracts api stratKris Chant
 
Build 2017 - B8002 - Introducing Adaptive Cards
Build 2017 - B8002 - Introducing Adaptive CardsBuild 2017 - B8002 - Introducing Adaptive Cards
Build 2017 - B8002 - Introducing Adaptive CardsWindows Developer
 
Using Mongoid with Ruby on Rails
Using Mongoid with Ruby on RailsUsing Mongoid with Ruby on Rails
Using Mongoid with Ruby on RailsNicholas Altobelli
 
How to build a scalable SNS using HBase
How to build a scalable SNS using HBaseHow to build a scalable SNS using HBase
How to build a scalable SNS using HBaseMu Chun Wang
 
GRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, Salto
GRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, SaltoGRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, Salto
GRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, SaltoDevOpsDays Tel Aviv
 
Mongo db eveningschemadesign
Mongo db eveningschemadesignMongo db eveningschemadesign
Mongo db eveningschemadesignMongoDB APAC
 
Advanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache CassandraAdvanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache CassandraDataStax Academy
 
Dev Jumpstart: Build Your First App with MongoDB
Dev Jumpstart: Build Your First App with MongoDBDev Jumpstart: Build Your First App with MongoDB
Dev Jumpstart: Build Your First App with MongoDBMongoDB
 
MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...
MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...
MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...Prasoon Kumar
 
Freeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS ArchitectureFreeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS ArchitectureDavid Hoerster
 
Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...
Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...
Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...Databricks
 
Building Your First App with MongoDB Stitch
Building Your First App with MongoDB StitchBuilding Your First App with MongoDB Stitch
Building Your First App with MongoDB StitchMongoDB
 
[MongoDB.local Bengaluru 2018] Keynote
[MongoDB.local Bengaluru 2018] Keynote[MongoDB.local Bengaluru 2018] Keynote
[MongoDB.local Bengaluru 2018] KeynoteMongoDB
 
Lessons Learned with Cassandra and Spark at the US Patent and Trademark Office
Lessons Learned with Cassandra and Spark at the US Patent and Trademark OfficeLessons Learned with Cassandra and Spark at the US Patent and Trademark Office
Lessons Learned with Cassandra and Spark at the US Patent and Trademark OfficeDataStax Academy
 
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentos
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentosConceptos básicos. seminario web 3 : Diseño de esquema pensado para documentos
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentosMongoDB
 
Aprimorando sua Aplicação com Ext JS 4 - BrazilJS
Aprimorando sua Aplicação com Ext JS 4 - BrazilJSAprimorando sua Aplicação com Ext JS 4 - BrazilJS
Aprimorando sua Aplicação com Ext JS 4 - BrazilJSLoiane Groner
 
Introduction to Swagger
Introduction to SwaggerIntroduction to Swagger
Introduction to SwaggerKnoldus Inc.
 
[MongoDB.local Bengaluru 2018] Introduction to MongoDB Stitch
[MongoDB.local Bengaluru 2018] Introduction to MongoDB Stitch[MongoDB.local Bengaluru 2018] Introduction to MongoDB Stitch
[MongoDB.local Bengaluru 2018] Introduction to MongoDB StitchMongoDB
 
MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...
MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...
MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...MongoDB
 

Similar a SQL Saturday Madrid 2019 - Data model with Azure Cosmos DB (20)

Write better code faster with rest data contracts api strat
Write better code faster with rest data contracts   api stratWrite better code faster with rest data contracts   api strat
Write better code faster with rest data contracts api strat
 
Build 2017 - B8002 - Introducing Adaptive Cards
Build 2017 - B8002 - Introducing Adaptive CardsBuild 2017 - B8002 - Introducing Adaptive Cards
Build 2017 - B8002 - Introducing Adaptive Cards
 
Using Mongoid with Ruby on Rails
Using Mongoid with Ruby on RailsUsing Mongoid with Ruby on Rails
Using Mongoid with Ruby on Rails
 
How to build a scalable SNS using HBase
How to build a scalable SNS using HBaseHow to build a scalable SNS using HBase
How to build a scalable SNS using HBase
 
GRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, Salto
GRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, SaltoGRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, Salto
GRAPHQL TO THE RES(T)CUE, ELLA SHARAKANSKI, Salto
 
Mongo db eveningschemadesign
Mongo db eveningschemadesignMongo db eveningschemadesign
Mongo db eveningschemadesign
 
Advanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache CassandraAdvanced Data Modeling with Apache Cassandra
Advanced Data Modeling with Apache Cassandra
 
Dev Jumpstart: Build Your First App with MongoDB
Dev Jumpstart: Build Your First App with MongoDBDev Jumpstart: Build Your First App with MongoDB
Dev Jumpstart: Build Your First App with MongoDB
 
MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...
MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...
MongoDB Introduction talk at Dr Dobbs Conference, MongoDB Evenings at Bangalo...
 
Freeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS ArchitectureFreeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS Architecture
 
#CNX14 - Intro to Force
#CNX14 - Intro to Force#CNX14 - Intro to Force
#CNX14 - Intro to Force
 
Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...
Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...
Graph Features in Spark 3.0: Integrating Graph Querying and Algorithms in Spa...
 
Building Your First App with MongoDB Stitch
Building Your First App with MongoDB StitchBuilding Your First App with MongoDB Stitch
Building Your First App with MongoDB Stitch
 
[MongoDB.local Bengaluru 2018] Keynote
[MongoDB.local Bengaluru 2018] Keynote[MongoDB.local Bengaluru 2018] Keynote
[MongoDB.local Bengaluru 2018] Keynote
 
Lessons Learned with Cassandra and Spark at the US Patent and Trademark Office
Lessons Learned with Cassandra and Spark at the US Patent and Trademark OfficeLessons Learned with Cassandra and Spark at the US Patent and Trademark Office
Lessons Learned with Cassandra and Spark at the US Patent and Trademark Office
 
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentos
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentosConceptos básicos. seminario web 3 : Diseño de esquema pensado para documentos
Conceptos básicos. seminario web 3 : Diseño de esquema pensado para documentos
 
Aprimorando sua Aplicação com Ext JS 4 - BrazilJS
Aprimorando sua Aplicação com Ext JS 4 - BrazilJSAprimorando sua Aplicação com Ext JS 4 - BrazilJS
Aprimorando sua Aplicação com Ext JS 4 - BrazilJS
 
Introduction to Swagger
Introduction to SwaggerIntroduction to Swagger
Introduction to Swagger
 
[MongoDB.local Bengaluru 2018] Introduction to MongoDB Stitch
[MongoDB.local Bengaluru 2018] Introduction to MongoDB Stitch[MongoDB.local Bengaluru 2018] Introduction to MongoDB Stitch
[MongoDB.local Bengaluru 2018] Introduction to MongoDB Stitch
 
MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...
MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...
MongoDB .local Chicago 2019: Best Practices for Working with IoT and Time-ser...
 

Más de Alberto Diaz Martin

Microsoft 365 Virtual 2020 Spain - Microsoft Graph Search API
Microsoft 365 Virtual 2020 Spain - Microsoft Graph Search APIMicrosoft 365 Virtual 2020 Spain - Microsoft Graph Search API
Microsoft 365 Virtual 2020 Spain - Microsoft Graph Search APIAlberto Diaz Martin
 
DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...
DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...
DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...Alberto Diaz Martin
 
DotNet Conf Madrid 2019 - Whats New in ML.NET
DotNet Conf Madrid 2019 - Whats New in ML.NETDotNet Conf Madrid 2019 - Whats New in ML.NET
DotNet Conf Madrid 2019 - Whats New in ML.NETAlberto Diaz Martin
 
DotNet Conf Madrid 2019 - ASP.NET Core 3
DotNet Conf Madrid 2019 - ASP.NET Core 3DotNet Conf Madrid 2019 - ASP.NET Core 3
DotNet Conf Madrid 2019 - ASP.NET Core 3Alberto Diaz Martin
 
SharePoint Saturday Madrid 2019 - Productivity based on AI
SharePoint Saturday Madrid 2019 - Productivity based on AISharePoint Saturday Madrid 2019 - Productivity based on AI
SharePoint Saturday Madrid 2019 - Productivity based on AIAlberto Diaz Martin
 
Dynamics Saturday Madrid 2019 - AI to improve productivity
Dynamics Saturday Madrid 2019 - AI to improve productivityDynamics Saturday Madrid 2019 - AI to improve productivity
Dynamics Saturday Madrid 2019 - AI to improve productivityAlberto Diaz Martin
 
TenerifeDev - NLPs and how to develop for Alexa and Google Assistant
TenerifeDev - NLPs and how to develop for Alexa and Google AssistantTenerifeDev - NLPs and how to develop for Alexa and Google Assistant
TenerifeDev - NLPs and how to develop for Alexa and Google AssistantAlberto Diaz Martin
 
NetCoreConf Barcelona 2019 - DotNet Assistants
NetCoreConf Barcelona 2019 - DotNet AssistantsNetCoreConf Barcelona 2019 - DotNet Assistants
NetCoreConf Barcelona 2019 - DotNet AssistantsAlberto Diaz Martin
 
Global Integration Bootcamp 2018 - Gobierno de APIs
Global Integration Bootcamp 2018 - Gobierno de APIsGlobal Integration Bootcamp 2018 - Gobierno de APIs
Global Integration Bootcamp 2018 - Gobierno de APIsAlberto Diaz Martin
 
Gab 2018 seguridad y escalado en azure service fabric
Gab 2018   seguridad y escalado en azure service fabricGab 2018   seguridad y escalado en azure service fabric
Gab 2018 seguridad y escalado en azure service fabricAlberto Diaz Martin
 
CrossDvlpu - REACT para desarrolladores de ASP.NET
CrossDvlpu - REACT para desarrolladores de ASP.NETCrossDvlpu - REACT para desarrolladores de ASP.NET
CrossDvlpu - REACT para desarrolladores de ASP.NETAlberto Diaz Martin
 
Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365
Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365
Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365Alberto Diaz Martin
 
Azure4Research - Big Data Analytics con Hadoop, Spark y Power BI
Azure4Research - Big Data Analytics con Hadoop, Spark y Power BIAzure4Research - Big Data Analytics con Hadoop, Spark y Power BI
Azure4Research - Big Data Analytics con Hadoop, Spark y Power BIAlberto Diaz Martin
 
ENCAMINA - El flash de Inteligencia Artificial
ENCAMINA - El flash de Inteligencia ArtificialENCAMINA - El flash de Inteligencia Artificial
ENCAMINA - El flash de Inteligencia ArtificialAlberto Diaz Martin
 
Ai & Data Analytics 2018 - Azure Databricks for data scientist
Ai & Data Analytics 2018 - Azure Databricks for data scientistAi & Data Analytics 2018 - Azure Databricks for data scientist
Ai & Data Analytics 2018 - Azure Databricks for data scientistAlberto Diaz Martin
 
Global AI Bootcamp Madrid - Azure Databricks
Global AI Bootcamp Madrid - Azure DatabricksGlobal AI Bootcamp Madrid - Azure Databricks
Global AI Bootcamp Madrid - Azure DatabricksAlberto Diaz Martin
 
TenerifeDev - Intro to Microservices
TenerifeDev - Intro to MicroservicesTenerifeDev - Intro to Microservices
TenerifeDev - Intro to MicroservicesAlberto Diaz Martin
 
TenerifeDev - Azure Service Fabric
TenerifeDev - Azure Service FabricTenerifeDev - Azure Service Fabric
TenerifeDev - Azure Service FabricAlberto Diaz Martin
 
Commit Conf 2018 - Extiende al asistente
Commit Conf 2018 - Extiende al asistenteCommit Conf 2018 - Extiende al asistente
Commit Conf 2018 - Extiende al asistenteAlberto Diaz Martin
 
Sps barcelona 2017 serverless para office 365
Sps barcelona 2017   serverless para office 365Sps barcelona 2017   serverless para office 365
Sps barcelona 2017 serverless para office 365Alberto Diaz Martin
 

Más de Alberto Diaz Martin (20)

Microsoft 365 Virtual 2020 Spain - Microsoft Graph Search API
Microsoft 365 Virtual 2020 Spain - Microsoft Graph Search APIMicrosoft 365 Virtual 2020 Spain - Microsoft Graph Search API
Microsoft 365 Virtual 2020 Spain - Microsoft Graph Search API
 
DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...
DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...
DotNet Conf Valencia 2019 - Building cloud native apps with .NRT core 3.0 and...
 
DotNet Conf Madrid 2019 - Whats New in ML.NET
DotNet Conf Madrid 2019 - Whats New in ML.NETDotNet Conf Madrid 2019 - Whats New in ML.NET
DotNet Conf Madrid 2019 - Whats New in ML.NET
 
DotNet Conf Madrid 2019 - ASP.NET Core 3
DotNet Conf Madrid 2019 - ASP.NET Core 3DotNet Conf Madrid 2019 - ASP.NET Core 3
DotNet Conf Madrid 2019 - ASP.NET Core 3
 
SharePoint Saturday Madrid 2019 - Productivity based on AI
SharePoint Saturday Madrid 2019 - Productivity based on AISharePoint Saturday Madrid 2019 - Productivity based on AI
SharePoint Saturday Madrid 2019 - Productivity based on AI
 
Dynamics Saturday Madrid 2019 - AI to improve productivity
Dynamics Saturday Madrid 2019 - AI to improve productivityDynamics Saturday Madrid 2019 - AI to improve productivity
Dynamics Saturday Madrid 2019 - AI to improve productivity
 
TenerifeDev - NLPs and how to develop for Alexa and Google Assistant
TenerifeDev - NLPs and how to develop for Alexa and Google AssistantTenerifeDev - NLPs and how to develop for Alexa and Google Assistant
TenerifeDev - NLPs and how to develop for Alexa and Google Assistant
 
NetCoreConf Barcelona 2019 - DotNet Assistants
NetCoreConf Barcelona 2019 - DotNet AssistantsNetCoreConf Barcelona 2019 - DotNet Assistants
NetCoreConf Barcelona 2019 - DotNet Assistants
 
Global Integration Bootcamp 2018 - Gobierno de APIs
Global Integration Bootcamp 2018 - Gobierno de APIsGlobal Integration Bootcamp 2018 - Gobierno de APIs
Global Integration Bootcamp 2018 - Gobierno de APIs
 
Gab 2018 seguridad y escalado en azure service fabric
Gab 2018   seguridad y escalado en azure service fabricGab 2018   seguridad y escalado en azure service fabric
Gab 2018 seguridad y escalado en azure service fabric
 
CrossDvlpu - REACT para desarrolladores de ASP.NET
CrossDvlpu - REACT para desarrolladores de ASP.NETCrossDvlpu - REACT para desarrolladores de ASP.NET
CrossDvlpu - REACT para desarrolladores de ASP.NET
 
Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365
Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365
Dynamics 365 Saturday Madrid 2018 - Otro ALM es posible para Dynamics 365
 
Azure4Research - Big Data Analytics con Hadoop, Spark y Power BI
Azure4Research - Big Data Analytics con Hadoop, Spark y Power BIAzure4Research - Big Data Analytics con Hadoop, Spark y Power BI
Azure4Research - Big Data Analytics con Hadoop, Spark y Power BI
 
ENCAMINA - El flash de Inteligencia Artificial
ENCAMINA - El flash de Inteligencia ArtificialENCAMINA - El flash de Inteligencia Artificial
ENCAMINA - El flash de Inteligencia Artificial
 
Ai & Data Analytics 2018 - Azure Databricks for data scientist
Ai & Data Analytics 2018 - Azure Databricks for data scientistAi & Data Analytics 2018 - Azure Databricks for data scientist
Ai & Data Analytics 2018 - Azure Databricks for data scientist
 
Global AI Bootcamp Madrid - Azure Databricks
Global AI Bootcamp Madrid - Azure DatabricksGlobal AI Bootcamp Madrid - Azure Databricks
Global AI Bootcamp Madrid - Azure Databricks
 
TenerifeDev - Intro to Microservices
TenerifeDev - Intro to MicroservicesTenerifeDev - Intro to Microservices
TenerifeDev - Intro to Microservices
 
TenerifeDev - Azure Service Fabric
TenerifeDev - Azure Service FabricTenerifeDev - Azure Service Fabric
TenerifeDev - Azure Service Fabric
 
Commit Conf 2018 - Extiende al asistente
Commit Conf 2018 - Extiende al asistenteCommit Conf 2018 - Extiende al asistente
Commit Conf 2018 - Extiende al asistente
 
Sps barcelona 2017 serverless para office 365
Sps barcelona 2017   serverless para office 365Sps barcelona 2017   serverless para office 365
Sps barcelona 2017 serverless para office 365
 

Último

Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
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
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
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
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
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
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
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
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 

Último (20)

Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
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
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
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
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
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
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 

SQL Saturday Madrid 2019 - Data model with Azure Cosmos DB

  • 1. #SQLSatMadrid Modelos de datos en Azure Cosmos DB Alberto Diaz Martin @adiazcan
  • 2. #SQLSatMadrid ALBERTO DÍAZ CTIO | Microsoft Azure MVP ENCAMINA https://blogs.encamina.com/ @adiazcan https://www.linkedin.com/in/albertodiazmartin/ Alberto Diaz cuenta con más de 15 años de experiencia en la Industria IT, todos ellos trabajando con tecnologías Microsoft. Actualmente, es Chief Technology Innovation Officer en ENCAMINA, liderando el desarrollo de software con tecnología Microsoft, y miembro del equipo de Dirección. Para la comunidad, trabaja como organizador y speaker de las conferencias más relevantes del mundo Microsoft en España, en las cuales es uno de los referentes en SharePoint, Office 365 y Azure. Autor de diversos libros y artículos en revistas profesionales y blogs, en 2013 empezó a formar parte del equipo de Dirección de CompartiMOSS, una revista digital sobre tecnologías Microsoft. Desde 2011 ha sido nombrado Microsoft MVP, reconocimiento que ha renovado por séptimo año consecutivo. Se define como un geek, amante de los smartphones y desarrollador. Fundador de TenerifeDev (www.tenerifedev.com), un grupo de usuarios de .NET en Tenerife, y coordinador de SUGES (Grupo de Usuarios de SharePoint de España, www.suges.es)
  • 4. Sigue #SQLSatMadrid Session’s objectives BETTER UNDERSTAND MODELING AND PARTITIONING ON COSMOS DB MODEL A REAL-WORLD EXAMPLE MAXIMIZE PERFORMANCE AND SCALABILITY APPRECIATE HOW IT DIFFERS FROM RELATIONAL MODELING
  • 5. Sigue #SQLSatMadrid MongoDB Table API Turnkey global distribution Elastic scale out of storage & throughput Guaranteed low latency at the 99th percentile Comprehensive SLAs Five well-defined consistency models Azure Cosmos DB DocumentColumn-family Key-value Graph Core (SQL) API
  • 7. # 904 Sigue #SQLSatMadrid Our domain Users can create posts. Users can also like and add comments to posts. A front page displays a feed of recently created posts. It is possible to list all posts for a particular user. It is also possible to list all comments of a post and all users who have liked a post. A post is displayed with its author's username and a count of comments and likes. Comments and likes are also displayed with the username of their authors. When displayed as lists, posts only present a truncated summary of their content.
  • 8. Sigue #SQLSatMadrid Maybe you instantly think about…
  • 9. # 904 Sigue #SQLSatMadrid Start by identifying the access patterns What are the requests that our design will have to serve? To make it easier to follow, categorize them as: Command (write request) Query (read-only request)
  • 10. # 904 Sigue #SQLSatMadrid Start by identifying the access patterns [C1] Create/edit a user's profile [Q1] Retrieve a user's profile [C2] Create/edit a post [Q2] Retrieve a post [Q3] List a user's posts in short form [C3] Create a comment [Q4] List a post's comments [C4] Like a post [Q5] List a post's likes [Q6] List the x most recent posts in short form (feed)
  • 11. # 904 Sigue #SQLSatMadrid The rules of the game
  • 12. # 904 Sigue #SQLSatMadrid The rules of the game: data model In a Cosmos DB database, we store documents in collections like rows in a table? user likepost comment users likesposts comments NO
  • 13. # 904 Sigue #SQLSatMadrid The rules of the game: data model In a Cosmos DB database, we store documents in collections user likepost comment users posts
  • 14. # 904 Sigue #SQLSatMadrid The rules of the game: provisioned performance Expected performance has to be provisioned Expressed in Request Units per second (RU/s) Represents the "cost" of a request in terms of CPU, memory and I/O Performance can be provisioned: at the database-level at the collection-level Provisioned performance can be changed programmatically with API calls
  • 15. # 904 Sigue #SQLSatMadrid The rules of the game: partitioning Cosmos DB achieves horizontal scalability by partitioning your data
  • 16. # 904 Sigue #SQLSatMadrid The rules of the game: partitioning Cosmos DB achieves horizontal scalability by partitioning your data logical partitions Logical partitions group your data according to the collection's partition key 'userId': 'abc' 'userId': 'def' 'userId': 'ghi'
  • 17. # 904 Sigue #SQLSatMadrid The rules of the game: partitioning A good partition key ensures well-balanced partitions Both in terms of storage and in terms of throughput Ideally, read queries should get all their results from one partition 'userId': 'abc' 'userId': 'def' 'userId': 'ghi' SELECT * FROM u WHERE u.userId = 'def'
  • 18. Sigue #SQLSatMadrid V1: a first shot { "id": "<user-id>", "username": "<user-username>" } { "id": "<post-id>", "userId": "<post-author-id>", "title": "<post-title>", "content": "<post-content>", "creationDate": "<post-creation-date>" } { "id": "<comment-id>", "postId": "<post-id>", "userId": "<comment-author-id>", "content": "<comment-content>", "creationDate": "<comment-creation-date>" } { "id": "<like-id>", "postId": "<post-id>", "userId": "<liker-id>", "creationDate": "<like-creation-date>" }
  • 19. Sigue #SQLSatMadrid To embed or to reference? { "id": "…", "relatedItemId": "<related-item-id>" } { "id": "<related-item-id>", "relatedData": "…" } { "id": "…", "relatedItem": { "relatedData": "…" } }
  • 20. Sigue #SQLSatMadrid To embed or to reference? Embed when: 1:1 1:few Items queried together Items updated together Reference when: 1:many (unbounded) Many:many Items updated independently
  • 21. Sigue #SQLSatMadrid V1: a first shot { "id": "<user-id>", "username": "<user-username>" } users PK: id posts PK: postId { "id": "<post-id>", "type": "post", "postId": "<post-id>", "userId": "<post-author-id>", "title": "<post-title>", "content": "<post-content>", "creationDate": "<post-creation-date>" } { "id": "<comment-id>", "type": "comment", "postId": "<post-id>", "userId": "<comment-author-id>", "content": "<comment-content>", "creationDate": "<comment-creation-date>" } { "id": "<like-id>", "type": "like", "postId": "<post-id>", "userId": "<liker-id>", "creationDate": "<like-creation-date>" }
  • 22. # 904 Sigue #SQLSatMadrid How well does our model perform? Benchmarked against a dummy dataset 100,000 users 5 – 50 posts / user 0 – 25 comments / post 0 – 100 likes / post users posts 100k docs 95+M docs 100 GB
  • 23. Sigue #SQLSatMadrid Create/edit a user’s profile C1 users PK: id posts PK: postId 7 ms / 5.71 RU
  • 24. Sigue #SQLSatMadrid Retrieve a user's profile Q1 users PK: id posts PK: postId SELECT * FROM u WHERE u.id = '<user-id>' 3 ms / 2.90 RU
  • 25. Sigue #SQLSatMadrid Create/edit a post C2 users PK: id posts PK: postId
  • 26. Sigue #SQLSatMadrid Retrieve a post Q2 users PK: id posts PK: postId SELECT * FROM p WHERE p.postId = '<post-id>' AND p.type = 'post' SELECT u.username FROM u WHERE u.id = '<post-author-id>' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'like' 9 ms / 19.54 RU
  • 27. Sigue #SQLSatMadrid List a user's posts in short form Q3 users PK: id posts SELECT * FROM p WHERE p.userId = '<author-id>' AND p.type = 'post' SELECT u.username FROM u WHERE u.id = '<post-author-id>' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'like' PK: postId 130 ms / 619.41 RU
  • 28. Sigue #SQLSatMadrid Create a comment C3 users PK: id posts PK: postId
  • 29. Sigue #SQLSatMadrid List a post's comments Q4 users PK: id posts PK: postId SELECT * FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT u.username FROM u WHERE u.id = '<comment-author-id>' 23 ms / 27.72 RU
  • 30. Sigue #SQLSatMadrid Like a post C4 users PK: id posts PK: postId
  • 31. Sigue #SQLSatMadrid List a post's likes Q5 users PK: id posts PK: postId SELECT * FROM p WHERE p.postId = '<post-id>' AND p.type = 'like' SELECT u.username FROM u WHERE u.id = '<liker-id>'
  • 32. Sigue #SQLSatMadrid List the x most recent posts in short form (feed) Q6 users PK: id posts PK: postId SELECT TOP <x> * FROM p WHERE p.type = 'post' ORDER BY p.creationDate DESC SELECT u.username FROM u WHERE u.id = '<post-author-id>' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'like' 306 ms / 2063.54 RU
  • 33. # 904 Sigue #SQLSatMadrid V1: performance issues Having to issue multiple queries to handle a single request Issuing queries that don't filter on the partition key, leading to a partition scan
  • 34. Sigue #SQLSatMadrid Retrieve a post Q2 users PK: id posts PK: postId SELECT * FROM p WHERE p.postId = '<post-id>' AND p.type = 'post' SELECT u.username FROM u WHERE u.id = '<post-author-id>' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'like'
  • 35. Sigue #SQLSatMadrid V2: introducing denormalization users PK: id posts PK: postId { "id": "<post-id>", "type": "post", "postId": "<post-id>", "userId": "<post-author-id>", "userUsername": "<post-author- username>", "title": "<post-title>", "content": "<post-content>", "commentCount": <number-of-comments>, "likeCount": <number-of-likes>, "creationDate": "<post-creation-date>" } { "id": "<comment-id>", "type": "comment", "postId": "<post-id>", "userId": "<comment-author-id>", "userUsername": "<comment-author-username>", "content": "<comment-content>", "creationDate": "<comment-creation-date>" } { "id": "<like-id>", "type": "like", "postId": "<post-id>", "userId": "<liker-id>", "userUsername": "<liker-username>", "creationDate": "<like-creation-date>" }
  • 36. # 904 Sigue #SQLSatMadrid Denormalizing within the same logical partition with stored procedures Written in Javascript Scoped to a single logical partition Executed as atomic transactions
  • 37. Sigue #SQLSatMadrid Create a comment C3 users PK: id posts PK: postId function createComment(postId, comment) { var collection = getContext().getCollection(); collection.readDocument( `${collection.getAltLink()}/docs/${postId}`, function (err, post) { post.commentCount++; collection.replaceDocument( post._self, post, function (err) { comment.postId = postId; collection.createDocument( collection.getSelfLink(), comment ); } ); }); }
  • 38. Sigue #SQLSatMadrid Denormalizing across logical partitions and containers with the change feed
  • 39. Sigue #SQLSatMadrid Denormalizing usernames into posts function updateUsername(userId, username) { var collection = getContext().getCollection(); collection.queryDocuments( collection.getSelfLink(), `SELECT * FROM p WHERE p.userId = '${userId}'`, function (err, results) { for (var i in results) { var doc = results[i]; doc.userUsername = username; collection.replaceDocument( collection.getSelfLink(), doc); } }); }
  • 40. Sigue #SQLSatMadrid Retrieve a post Q2 users PK: id posts PK: postId SELECT * FROM p WHERE p.postId = '<post-id>' AND p.type = 'post' SELECT u.username FROM u WHERE u.id = '<post-author-id>' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'like' 3 ms / 5.40 RU
  • 41. Sigue #SQLSatMadrid List a post's comments Q4 users PK: id posts PK: postId SELECT * FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT u.username FROM u WHERE u.id = '<comment-author-id>' Q4 4 ms / 7.72 RU
  • 42. Sigue #SQLSatMadrid List a post's likes Q5 users PK: id posts PK: postId SELECT * FROM p WHERE p.postId = '<post-id>' AND p.type = 'like' SELECT u.username FROM u WHERE u.id = '<liker-id>' Q5
  • 43. Sigue #SQLSatMadrid List a user's posts in short form Q3 users PK: id posts SELECT * FROM p WHERE p.userId = '<author-id>' AND p.type = 'post' SELECT u.username FROM u WHERE u.id = '<post-author-id>' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'like' PK: postId
  • 44. Sigue #SQLSatMadrid V3: denormalizing entire documents users PK: id posts PK: postId
  • 45. Sigue #SQLSatMadrid V3: denormalizing entire documents users PK: id posts PK: postId { "id": "<post-id>", "type": "post", "userId": "<post-author-id>", "userUsername": "<post-author- username>", "title": "<post-title>", "content": "<post-content>", "commentCount": <number-of-comments>, "likeCount": <number-of-likes>, "creationDate": "<post-creation-date>" } PK: userId { "id": "<user-id>", "type": "user", "userId": "<user-id>", "username": "<user-username>" }
  • 46. Sigue #SQLSatMadrid Denormalizing documents with the change feed posts users truncate content if (type == 'post')
  • 47. Sigue #SQLSatMadrid PK: userId List a user's posts in short form Q3 users posts SELECT * FROM p WHERE p.userId = '<author-id>' AND p.type = 'post' PK: postId 4 ms / 6.46 RU
  • 48. Sigue #SQLSatMadrid List the x most recent posts in short form (feed) Q6 users PK: id posts PK: postId SELECT TOP <x> * FROM p WHERE p.type = 'post' ORDER BY p.creationDate DESC SELECT u.username FROM u WHERE u.id = '<post-author-id>' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'comment' SELECT COUNT(1) FROM p WHERE p.postId = '<post-id>' AND p.type = 'like'
  • 49. Sigue #SQLSatMadrid V3: denormalizing entire documents users posts PK: postId PK: userId
  • 50. Sigue #SQLSatMadrid V3: denormalizing entire documents users posts PK: postId PK: userId { "id": "<post-id>", "type": "post", "userId": "<post-author-id>", "userUsername": "<post-author- username>", "title": "<post-title>", "content": "<post-content>", "commentCount": <number-of-comments>, "likeCount": <number-of-likes>, "creationDate": "<post-creation-date>" } feed PK: type
  • 51. Sigue #SQLSatMadrid Denormalizing documents with the change feed posts users truncate content if (type == 'post')
  • 52. Sigue #SQLSatMadrid Denormalizing documents with the change feed posts users truncate content if (type == 'post') feed post-trigger: truncate container
  • 53. Sigue #SQLSatMadrid List the x most recent posts in short form (feed) Q6 users PK: id posts PK: postId SELECT TOP <x> * FROM p WHERE p.type = 'post' ORDER BY p.creationDate DESC feed PK: type9 ms / 16.97 RU
  • 54. Sigue #SQLSatMadrid Our final design users posts feed user post post post like comment
  • 55. Sigue #SQLSatMadrid Our final design users posts feed if (type == 'user') truncate content if (type == 'post') updateUsername()
  • 56. # 904 Sigue #SQLSatMadrid Denormalization can be added later V1 was not that bad! You can add denormalization later The change feed is persistent Run a one-time catch-up operation Monitor your database performance and setup alerts V1 C1 7 ms / 5.71 RU Q1 3 ms / 2.90 RU C2 9 ms / 8.76 RU Q2 9 ms / 19.54 RU Q3 130 ms / 619.41 RU C3 7 ms / 8.57 RU Q4 23 ms / 27.72 RU C4 6 ms / 7.05 RU Q5 59 ms / 58.92 RU Q6 306 ms / 2063.54 RU
  • 57. # 904 Sigue #SQLSatMadrid An overall look at performance V1 C1 7 ms / 5.71 RU Q1 3 ms / 2.90 RU C2 9 ms / 8.76 RU Q2 9 ms / 19.54 RU Q3 130 ms / 619.41 RU C3 7 ms / 8.57 RU Q4 23 ms / 27.72 RU C4 6 ms / 7.05 RU Q5 59 ms / 58.92 RU Q6 306 ms / 2063.54 RU V2 V3 7 ms / 5.71 RU 7 ms / 5.71 RU 3 ms / 2.90 RU 3 ms / 2.90 RU 9 ms / 8.76 RU 9 ms / 8.76 RU 3 ms / 5.11 RU 3 ms / 5.11 RU 28 ms / 201.54 RU 4 ms / 6.46 RU 7 ms / 15.27 RU 7 ms / 15.27 RU 4 ms / 7.72 RU 4 ms / 7.72 RU 7 ms / 14.67 RU 7 ms / 14.67 RU 4 ms / 8.92 RU 4 ms / 8.92 RU 83 ms / 532.33 RU 9 ms / 16.97 RU
  • 58. # 904 Sigue #SQLSatMadrid What about the cost of denormalization? We optimized for a read-heavy scenario Reads >> writes Q6 went from 2,000+ to 17 RUs (120x optimization) Saved 1920 RUs by denormalizing posts at ~10RUs / document All depends on your specific scenario and access patterns
  • 59. # 904 Sigue #SQLSatMadrid Most importantly: what’s our scalability? V3: limitless! Performance will not depend on number of documents number of users number of posts Whether you have 10 or 10M users, query latency will always be the same V3 C1 7 ms / 5.71 RU Q1 3 ms / 2.90 RU C2 9 ms / 8.76 RU Q2 3 ms / 5.11 RU Q3 4 ms / 6.46 RU C3 7 ms / 14.67 RU Q4 4 ms / 7.72 RU C4 7 ms / 14.67 RU Q5 4 ms / 8.92 RU Q6 9 ms / 16.97 RU
  • 60. # 904 Sigue #SQLSatMadrid Take away Don’t think as relational database Iterate your model and denormalize Create aggregatea and materialize views Denormalize