Cosmos DB

Before we start

Survey

Who am I?

Piotr Stapp

  • Unique name - just sing a song: "Don't Stapp me know" ;)
  • CEO @ Dotnetomaniak
  • VP @ devWarsztaty
  • Software architect @ Demant Technology Center
  • M.Sc (distction) Oxford Brooks University in Web Tech
  • M.Sc. Warsaw University of Technology in Computer Science
  • And ......

Databases in Azure

Options (built-in)

  • SQL
    • Azure SQL
    • Azure Database for PostgreSQL

    • Azure Database for MySQL

    • Azure Database for MariaDB

  • NoSQL
    • Azure Cosmos DB
    • Azure Cache for Redis
    • Table storage (simple key value)
  • Self-hosted :)

Β 

Where is MongoDB or Cassandra?

Azure Cosmos DB

Survey result

What's inside?

Relational DB

Document DB

Relational vs document

Model

  • User
  • Address
  • Orders
{
    "id": "9f4657a4-43e3-4a47-9392-6c418035d552",
    "key": "7a9f3c4b-3adc-4fb1-a539-47734db30ae0",
    "user": {
        "Id": 215,
        "FirstName": "Wayne",
        "LastName": "Hayes",
        "FullName": "Wayne Hayes",
        "UserName": "Wayne19",
        "UserNameLower": "wayne19",
        "Email": "Wayne.Hayes@hotmail.com",
        "CartId": "a78e749e-ebb2-434c-b658-6795ada0e086",
        "Gender": 0,
        "Orders": [
            {
                "OrderId": 217,
                "Item": "banana",
                "Quantity": 1
            }
        ],
        "Address": {
            "Type": "company",
            "Address": {
                "City": "Florineport",
                "ZipCode": "38056-0892",
                "Street": "Miller Center",
                "CountryCode": "QA"
            }
        }
    },
    "_rid": "vE5vAKy0d4mWzgMAAAAAAA==",
    "_self": "dbs/vE5vAA==/colls/vE5vAKy0d4k=/docs/vE5vAKy0d4mWzgMAAAAAAA==/",
    "_etag": "\"0e0000c6-0000-0d00-0000-6005f1f10000\"",
    "_attachments": "attachments/",
    "_ts": 1611002353
}

Using

Azure CLI

- Creating is easy :)

- 5-15 minutes :(

- I will cheat a bit




az cosmosdb create \
   --name $COSMOS_DB_NAME \
   --resource-group $group \
   --kind MongoDB

Basics

Rules

  • No JOIN at all (only client side)
  • Bad design == heavy queries == $$$
  • Indexes are important πŸ€ͺ
  • Relations:
    • Embedded (like Orders)
    • Reference (like CartId)

DEMO

Let's look on it 😁

DEMO - Simple search

--simple select
SELECT *
FROM c
WHERE c.user.LastName = 'Bernhard'

--simple count
SELECT count(1)
FROM c
WHERE c.user.LastName = 'Bernhard'

DEMO - Nested search

SELECT c.id, c.user.Id, 
	c.user.FirstName, c.user.LastName,
	o.Item, o.Quantity
FROM c
JOIN o IN c.user.Orders
WHERE 1=1
AND c.user.LastName = 'Bernhard'
AND o.Item='kiwi'
and o.Quantity=1

Request Units (RU)

  • Abstraction over:
    • CPU
    • Memory
    • IOPS
  • Read 1 KB item costs 1RU

Request Units (RU)

  • Bullet One
  • Bullet Two
  • Bullet Three

DEMO - Calculator

DEMO - Bad one

πŸ™‰πŸ™ŠπŸ™ˆ

SELECT count(1)
FROM c
JOIN o IN c.user.Orders
WHERE 1=1
AND o.Item>'kiwi'
and o.Quantity=1

High Availability

Azure Cosmos DB

Theory

PACELC theoremΒ is an extension to the CAP theorem. It states that in case of network partitioning (P) in a distributed computer system, one has to choose between availability (A) and consistency (C) (as per the CAP theorem), but else (E), even when the system is running normally in the absence of partitions, one has to choose between latency (L) and consistency (C).

(wikipedia)

Azure Cosmos DB

DEMO SLA DOCUMENTATION

(sorry)

Consistency levels

Consistency levels

  • Strong
  • Bounded Staleness
  • Session
  • Consistent Prefix
  • Eventual

Strong

  • Bullet One
  • Bullet Two
  • Bullet Three

Bounded Staleness

  • Bullet One
  • Bullet Two
  • Bullet Three

Session

  • Bullet One
  • Bullet Two
  • Bullet Three

Consistent Prefix

  • Bullet One
  • Bullet Two
  • Bullet Three

Eventual

  • Bullet One
  • Bullet Two
  • Bullet Three

Indexes

Types

  • kind - range (default) or hash
  • precisionΒ - default is -1==maximum
  • dataType - string or number

Indexes

{
    "indexingMode": "consistent",
    "automatic": true,
    "includedPaths": [
        {
            "path": "/*"
        }
    ],
    "excludedPaths": [
        {
            "path": "/user/Address/*"
        },
        {
            "path": "/\"_etag\"/?"
        }
    ],
    "compositeIndexes": [
        [
            {
                "path": "/user/LastName",
                "order": "ascending"
            },
            {
                "path": "/user/FirstName",
                "order": "descending"
            }
        ]
    ]
}

DEMO - Indexes

SELECT count(1)
FROM c
JOIN o IN c.user.Orders
where 1=1
AND c.user.LastName > 'Z'
AND c.user.FirstName < 'L'
AND CONTAINS(c.user.Email, 'gmail', true)

DEMO - Indexes

-- run on data & db2
SELECT count(1)
FROM c
where c.user.Address.Address.CountryCode="CZ"

Composite indexes

--only on db2
SELECT * FROM c
ORDER BY c.user.LastName desc,
         c.user.FirstName asc

Backup

Managed backup

  • Default:
    • every 4 hours
    • only last 2
  • Not default -> let's check 😁

How is it working?

  • Bullet One
  • Bullet Two
  • Bullet Three

Restore

  • Bullet One
  • Bullet Two
  • Bullet Three

Pricing tips&tricks

Title Text

  • Bullet One
  • Bullet Two
  • Bullet Three

3 options

  • Manual scale
  • Autoscale (in theory 1.5x manual)
  • Serverless (new option)
  • Free tier

Serverless

  • 100k RU == 0.0258 EUR
  • Availability Zone 1.25x
  • Multiregion - not supported yet

Manual / provisioned

  • 100 RU == ~4.92 EUR
  • Minimum 400 RU per container in container scaling mode
  • In database mode formula is more complicated: MAX([containers count]x100RU, 400 RU)

Autoscale

  • 100 RU autoscale == 150 RU manual
  • Autoscale is always a range: from 10% X to 100% X
  • Database model pricing is "better"
  • Minimum for 25 containers is still 400 RU, instead of 2500 RU

Free tier

With free tier, you'll get the first 400 RU/s and 5 GB of storage in this account for free. To keep your account free, keep the total RU/s across all resources in the account to 400 RU/s.

ORM - problems

DEMO - Translation

var query = _dbClient.Where<UserDocument>( _collectionUri,
 d =>d.User.UserName.ToLower() == criteria.SearchString);

SELECT * FROM c
WHERE LOWER(c.user.UserName) = "{search}" 

------------------------------

var query = _dbClient.Where<UserDocument>( _collectionUri,
 d => d.User.UserName.Equals(originalSearchString,
 		StringComparison.OrdinalIgnoreCase)); 

SELECT * FROM c
WHERE STRINGEQUALS(c.user.UserName, "{search}", true)

----

var query = _dbClient.Where<UserDocument>( _collectionUri,
 d => d.User.UserNameLower == originalSearchString); 
 
SELECT * FROM c
WHERE c.user.UserNameLower = "{search}"

More stappuff

Things

  • Different languages and types than SQL & documents:
    • Mongo, Cassandra, Gremlin, etcd ...
  • Geospatial data + search
  • Storing & querying dates
  • Change feed
  • ...

The end?

Not yet :)

Q&A

Twitter: @ptrstpp950

Made with Slides.com