{"id":1886,"date":"2020-10-22T09:00:28","date_gmt":"2020-10-22T16:00:28","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=1886"},"modified":"2020-12-14T11:24:08","modified_gmt":"2020-12-14T19:24:08","slug":"point-reads-versus-queries","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/point-reads-versus-queries\/","title":{"rendered":"Understanding the difference between point reads and queries in Azure Cosmos DB"},"content":{"rendered":"<p>This blog is part one of a series of blogs (<a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/difference-between-null-and-undefined\/\">read part two here<\/a>) where we\u2019ll demystify commonly confused concepts for developers learning how to query in the Core (SQL) API in Azure Cosmos DB.<\/p>\n<p>First, we&#8217;ll take an in-depth look at the differences between point reads and queries.<\/p>\n<p>There are <strong>two <\/strong>ways to read data in Azure Cosmos DB: point reads and queries. Most developers know that you can query data using Cosmos DB&#8217;s SQL query language, but not everyone realizes that point reads are an even more efficient way to read data. A point read is a key\/value lookup on a single <em>item ID<\/em>\u00a0and partition key.<\/p>\n<p>Here are the major differences between point reads and queries:<\/p>\n<table style=\"width: 50.9259%; height: 165px;\">\n<tbody>\n<tr style=\"height: 53px;\">\n<td style=\"height: 53px; width: 33.1731%;\" width=\"208\"><\/td>\n<td style=\"height: 53px; width: 33.1731%;\" width=\"208\"><strong>Point read<\/strong> (assumes 1 KB item)<\/td>\n<td style=\"width: 33.6538%;\" width=\"208\"><strong>Query<\/strong><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\"><strong>Latency<\/strong><\/td>\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\">Typically less than 10 ms<\/td>\n<td style=\"width: 33.6538%;\" width=\"208\">Variable<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\"><strong>RU charge<\/strong><\/td>\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\">1 RU<\/td>\n<td style=\"width: 33.6538%;\" width=\"208\">At least 2.3 RUs, variable<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\"><strong>Number of items returned<\/strong><\/td>\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\">1 item<\/td>\n<td style=\"width: 33.6538%;\" width=\"208\">Unlimited (if results size is too large, results are split across multiple pages)<\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\"><strong>Include partition key?<\/strong><\/td>\n<td style=\"height: 28px; width: 33.1731%;\" width=\"208\">Required<\/td>\n<td style=\"width: 33.6538%;\" width=\"208\">Recommended<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><span style=\"font-size: 12pt;\">In many cases, you can make simple changes in your app to rewrite simple queries as point reads. Most read-heavy workloads on Azure Cosmos D<\/span>B use a combination of both point reads and SQL queries. If you just need to read a single item, point reads are cheaper and faster than queries. Point reads can read the data directly and don&#8217;t require the query engine.<\/p>\n<h2><strong>Transforming queries to point reads:<\/strong><\/h2>\n<p>Let\u2019s imagine that Contoso Retail, a fictional company, has a large Cosmos <strong>orders <\/strong>container that has customers orders data. Each item in the <strong>orders <\/strong>container represents a separate customer\u2019s order and you can identify an order by its <strong>id <\/strong>value. The partition key of the <strong>orders <\/strong>container is <strong>customerId<\/strong>.<\/p>\n<p>Here\u2019s an example item in the <strong>orders<\/strong> container:<\/p>\n<pre>{\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"id\" : \"order0103\",\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"customerId\": \"TimS1234\"\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"order details\" : \u2026.\r\n}<\/pre>\n<p>Contoso Retail\u2019s app runs the following query on the <strong>orders<\/strong> container very frequently:<\/p>\n<pre><strong>SELECT * <\/strong>\r\n<strong>FROM c<\/strong>\r\n<strong>WHERE c.id = \"order0103\" AND c.customerId = \"TimS1234\"<\/strong><\/pre>\n<p>This query will cost a little under 3 RU\u2019s when executed. Because the query has an equality filter on <strong>customerId<\/strong> (the partition key), the query is an in-partition query.<\/p>\n<p>While this query is efficient, it could be written as a point read. Here\u2019s an example using the .NET SDK and an <strong>Order <\/strong>entity:<\/p>\n<pre>Order order = await container.ReadItemAsync&lt;Order&gt;(id: \"order0103\", partitionKey: new PartitionKey(\"TimS1234\"));<\/pre>\n<p>This point read operation will be slightly faster than the query and only use <strong>1 RU<\/strong>. This equates to an RU cost savings of <strong>66%<\/strong>! If the application ran this read operation frequently enough, this one line code change could translate to significant savings!<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<h2><strong>Utilizing the id property and partition key:<\/strong><\/h2>\n<p>You can only do a point read if you have both the id and partition key of an item. The id and partition key combination are also a globally unique key for items within an Azure Cosmos container. Developers know to take great care in selecting a good partition key choice for their Cosmos container. However, it is not as widely known that assigning meaningful values to the id property are required for doing point reads.<\/p>\n<p>Here\u2019s a data model which simply assigns a random guid as the <strong>id<\/strong> value:<\/p>\n<pre>{\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"id\": \"f2ef7v28f9802fa482\",\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"customerId\" : \"TimS1234\",\r\n           \"orderId\" : \"order0103\",\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"order details\" : \u2026.\r\n}\r\n\r\n<\/pre>\n<p>Consider this query, which filters on <strong>orderId<\/strong> (instead of <strong>id <\/strong>like in the previous example):<\/p>\n<pre><strong>SELECT * \r\nFROM c \r\nWHERE c.orderId = \"order0103\" AND c.customerId = \"TimS1234\"<\/strong><\/pre>\n<p>Unlike the previous query which searched for a specific id and partition key combination, this query includes the <strong>orderId<\/strong> instead. In order to rewrite this read as a point read, it is important that the operation include a specific <strong>id<\/strong> value. The <strong>id <\/strong>property is special, in the sense that no other properties in the item can be used to do point reads. In this case, it would be worthwhile to modify the data model to have the <strong>orderId <\/strong>\u00a0value stored as the <strong>id<\/strong> value. Assigning a meaningful <strong>id<\/strong> value makes it much more efficient to read data.<\/p>\n<p>Learn more:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/cosmos-db\/sql-query-getting-started\">Querying in Azure Cosmos DB<\/a><\/li>\n<li><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/cosmos-db\/how-to-model-partition-example\">Data modeling in Azure Cosmos DB<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog, we&#8217;ll look at the differences between point reads and queries in Azure Cosmos DB.<\/p>\n","protected":false},"author":12128,"featured_media":1894,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[14,19],"tags":[],"class_list":["post-1886","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-sql-api","category-tips-and-tricks"],"acf":[],"blog_post_summary":"<p>In this blog, we&#8217;ll look at the differences between point reads and queries in Azure Cosmos DB.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/1886","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/users\/12128"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=1886"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/1886\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/1894"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=1886"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=1886"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=1886"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}