<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Metaplane</title>
    <description>The latest articles on DEV Community by Metaplane (@metaplane).</description>
    <link>https://dev.to/metaplane</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1287749%2F5889d585-4b5e-4d67-a7af-74fd0b515ef3.png</url>
      <title>DEV Community: Metaplane</title>
      <link>https://dev.to/metaplane</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/metaplane"/>
    <language>en</language>
    <item>
      <title>How to manage tags for objects in Snowflake</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 08 Mar 2024 01:53:27 +0000</pubDate>
      <link>https://dev.to/metaplane/how-to-manage-tags-for-objects-in-snowflake-2lae</link>
      <guid>https://dev.to/metaplane/how-to-manage-tags-for-objects-in-snowflake-2lae</guid>
      <description>&lt;p&gt;Your data is the foundation for all the insights and strategies that drive your business forward. But the more data you collect, the higher the chances you encounter problems managing it.&lt;/p&gt;

&lt;p&gt;Without a solid data management strategy, you're essentially crossing your fingers in hopes that nothing goes wrong. At best, this approach leads to inefficiencies and increased costs as you scramble to patch up emerging problems. At worst, it triggers a detrimental cycle that erodes trust in the data and in the capabilities of the teams managing it.&lt;/p&gt;

&lt;p&gt;Thankfully, we have decades of industry best practices when implementing processes and tools to establish data governance practices that ensure trust in data. Effective data governance includes a wide range of principles and practices that may overlap with availability, usability, integrity, security, and compliance. And a big part of a proper data governance strategy in Snowflake involves using tags.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use tags in Snowflake
&lt;/h2&gt;

&lt;p&gt;Think of your data as a city. For fun, let’s call it NYC. Here, your data points are the people of NYC, data tables are skyscrapers, and your data warehouse is the entire metropolitan area. Without any form of organization, finding what you need when you need it would be like trying to locate a single person amongst the 8.5 million who live there (all without knowing anything about where they live or work).&lt;/p&gt;

&lt;p&gt;Data classification, in this analogy, is NYC’s zoning laws and addressing system. Residential, commercial, and industrial zones allow people to understand the general purpose and location of different areas. Tagging adds detailed signs and labels to each building, street, and neighborhood which provides additional, specific information beyond the basic structure provided by zoning and addresses.&lt;/p&gt;

&lt;p&gt;TLDR: Data classification groups data into categories (e.g., sensitive information, financial records, or customer data). Tagging is a data classification technique that further refines these categories. It enables data stewards to monitor sensitive data for compliance, discovery, protection, and resource usage use cases through either a centralized or decentralized data governance management approach.&lt;/p&gt;

&lt;p&gt;In Snowflake, a tag is a schema-level object that is assigned to another object as an arbitrary string value. This object-string match is then stored as a key-value pair that is unique to your schema.&lt;/p&gt;

&lt;p&gt;There are multiple benefits to using these in Snowflake:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of use&lt;/strong&gt;: You can define a tag once and apply it to as many different objects as desirable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag lineage&lt;/strong&gt;: Since tags are inherited, applying the tag to objects higher in the securable objects hierarchy results in the tag being applied to all child objects. For example, if a tag is set on a table, the tag will be inherited by all columns in that table. This makes it easier to track object relations in future audits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensitive data tracking&lt;/strong&gt;: Tags simplify identifying sensitive data (e.g. PII, Secrets). Then you add tags to tables, views, and columns, you can easily find many parts of the database that hold sensitive information just by searching for these tags. Once found, data stewards can figure out the best way to share it safely. They might limit who can see certain rows or decide if the data should be tokenized, fully masked, partially masked, or unmasked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource usage tracking&lt;/strong&gt;: Tags bring visibility to Snowflake resource usage. With data and metadata in the same system, analysts can quickly determine which resources consume the most Snowflake credits based on the tag definition (e.g. cost_center, department).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To support different management approaches and fulfill regulatory requirements, we recommend starting your tagging journey with a proper strategy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tagging Strategy
&lt;/h3&gt;

&lt;p&gt;Tags are extremely versatile; they can be linked to various types of objects, such as warehouses and tables, simultaneously. That’s why you need a tagging strategy before you begin object tagging in your account. This high-level plan should include: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A list of objects or datasets that need tags&lt;/li&gt;
&lt;li&gt;Tag naming convention&lt;/li&gt;
&lt;li&gt;Use cases for assigning specific tags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because tags are schema-level objects in Snowflake, they can be created in a single database/schema and assigned to other Snowflake objects across the account. You can choose between two approaches here: centralized or decentralized.&lt;/p&gt;

&lt;h3&gt;
  
  
  Centralized vs. Decentralized Approach
&lt;/h3&gt;

&lt;p&gt;In a centralized approach to tagging, a single team or department within the organization is responsible for defining, implementing, and managing the tagging strategy. This team sets the standards for how data is categorized, ensures consistency in tagging across all data assets, and monitors compliance with these standards. &lt;/p&gt;

&lt;p&gt;While it has plenty of benefits (consistency, control, and efficiency), a centralized approach can also lead to bottlenecks, as the centralized team may become a single point of failure or delay in the tagging process.&lt;/p&gt;

&lt;p&gt;Conversely, a decentralized approach allows individual departments or teams within an organization to define and manage their own tags according to their specific needs and use cases. This approach inherently has more flexibility, speed, and customization, but without overarching governance, it often leads to inconsistencies in tagging across the organization, which can complicate efforts to manage data at a company-wide level.&lt;/p&gt;

&lt;p&gt;Both approaches have their pros and cons, so the “right approach” really comes down to what’s most important to your organization. Either way, you’ll want to audit the tags periodically and make changes to the tagging plan according to the business context. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to create and manage tags in Snowflake
&lt;/h2&gt;

&lt;p&gt;When assigning tags, identifiers can either be consistent across multiple objects (e.g., all tagged objects labeled as sales) or vary to reflect different categories like engineering, marketing, or finance. To manage tags for objects in Snowflake using SQL commands, you generally create a tag, assign it to an object, and query that object by its tags. Here’s what each of those steps looks like:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create tags
&lt;/h3&gt;

&lt;p&gt;Creating a tag is a simple query with two parts : &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the &lt;code&gt;CREATE TAG&lt;/code&gt; statement&lt;/li&gt;
&lt;li&gt;Specify the tag string value when assigning the tag to an object. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s what that looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TAG tag_name;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Assign a Tag to an Object
&lt;/h3&gt;

&lt;p&gt;After creating a tag, you can assign it to an object such as a table, view, or column. You can do this either when you're creating the object or by altering an existing object.&lt;/p&gt;

&lt;p&gt;When creating a new object, you can assign a tag directly in the &lt;code&gt;CREATE&lt;/code&gt; statement by using the TAG clause as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE table_name (
 column_name datatype
) TAG tag_name = 'tag_value';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;table_name&lt;/code&gt;, &lt;code&gt;column_name&lt;/code&gt;, &lt;code&gt;datatype&lt;/code&gt;, &lt;code&gt;tag_name&lt;/code&gt;, and &lt;code&gt;tag_value&lt;/code&gt; with your specific details. Note that the &lt;code&gt;tag_value&lt;/code&gt; is the value you want to assign to this tag for the object.&lt;/p&gt;

&lt;p&gt;To assign a tag to an existing object, use the &lt;code&gt;ALTER&lt;/code&gt; statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALTER TABLE table_name SET TAG tag_name = 'tag_value';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example assigns a tag to a table, but you can similarly alter other types of objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Query Objects by Tags
&lt;/h3&gt;

&lt;p&gt;To find objects that have been assigned a specific tag or to see the tags associated with a particular object, you can use the SHOW TAGS statement or query the &lt;code&gt;INFORMATION_SCHEMA.TAG_REFERENCES&lt;/code&gt; view.&lt;/p&gt;

&lt;p&gt;To find objects with a specific tag, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOW TAGS LIKE 'tag_name';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will list objects that have been tagged with tag_name.&lt;/p&gt;

&lt;p&gt;To query specific tag assignments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM INFORMATION_SCHEMA.TAG_REFERENCES
WHERE TAG_NAME = 'tag_name';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query returns detailed information about objects tagged with tag_name, including the object type and tag value.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to manage tag quotas
&lt;/h2&gt;

&lt;p&gt;When specifying tags, here are some “quotas” to keep in mind for each object tag:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The string value for each tag can be up to 256 characters, with the option to specify allowed values for a tag. &lt;/li&gt;
&lt;li&gt;Snowflake allows a maximum number of 50 unique tags that can be set on a single object. &lt;/li&gt;
&lt;li&gt;In a CREATE or ALTER statement 100 is the maximum number of tags that can be specified in a single statement.&lt;/li&gt;
&lt;li&gt;For a table or view and its columns, the maximum number of unique tags that can be specified in a single CREATE or ALTER atement is 100. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Luckily, you can manage the tag quotas for an object easily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query the &lt;code&gt;TAG_REFERENCES&lt;/code&gt; view to determine the tag assignments.&lt;/li&gt;
&lt;li&gt;Unset the tag from the object or column. For objects, you can use the corresponding &lt;code&gt;ALTER... UNSET TAG&lt;/code&gt; command. For a table or view column, use the corresponding &lt;code&gt;ALTER { TABLE | VIEW } ... { ALTER | MODIFY } COLUMN ... UNSET TAG&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Drop the tag using a &lt;code&gt;DROP TAG&lt;/code&gt; statement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your organizational structure in Snowflake (i.e. tagging strategy) can also be applied in Metaplane. So if you want to &lt;a href="https://docs.metaplane.dev/reference/tagtables"&gt;apply a tag to a collection of tables&lt;/a&gt; identified by absolute paths like &lt;code&gt;{database}.{schema}.{table}&lt;/code&gt;, Metaplane can help. &lt;/p&gt;

&lt;p&gt;In Metaplane, you can bulk-apply tags from a &lt;a href="https://docs.metaplane.dev/docs/dashboards#custom-dashboards"&gt;custom dashboard&lt;/a&gt;. After navigating to the dashboard using the tag you'd like to bulk apply to objects or monitors, you'll be able to search and add additional objects. From there, you can &lt;a href="https://app.metaplane.dev/settings/alerts"&gt;set up alerting rules&lt;/a&gt; based on your tags (e.g. you can direct alerts for all data with a particular tag to a channel, email, or other alert destination). And &lt;a href="https://app.metaplane.dev/incidents"&gt;when an incident occurs in Metaplane&lt;/a&gt;, you can view the tags that are affected to help your team prioritize incidents that affect critical data over ones that don't.&lt;/p&gt;

&lt;p&gt;Want to see how Metaplane tags can improve your overall governance strategy? &lt;a href="https://www.metaplane.dev/book-a-demo"&gt;Talk to us&lt;/a&gt; or &lt;a href="https://metaplane.dev/signup"&gt;start a free trial today&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dataquality</category>
      <category>dataengineering</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Announcing Metaplane’s $13.8M Series A</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Tue, 05 Mar 2024 16:43:14 +0000</pubDate>
      <link>https://dev.to/metaplane/announcing-metaplanes-138m-series-a-2ik</link>
      <guid>https://dev.to/metaplane/announcing-metaplanes-138m-series-a-2ik</guid>
      <description>&lt;p&gt;&lt;strong&gt;Other links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PR Newswire&lt;/strong&gt;: &lt;a href="https://www.prnewswire.com/news-releases/metaplane-announces-13-8m-series-a-led-by-felicis-on-heels-of-rapid-growth-302079081.html"&gt;Metaplane Announces $13.8M Series A led by Felicis on Heels of Rapid Growth&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VentureBeat Exclusive&lt;/strong&gt;: &lt;a href="https://venturebeat.com/data-infrastructure/exclusive-metaplane-nets-13m-to-detect-data-anomalies-with-ai/"&gt;Metaplane nets $13M to detect data anomalies with AI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metaplane Blog&lt;/strong&gt;: &lt;a href="https://www.metaplane.dev/blog/metaplane-raises-13m-series-a"&gt;Announcing Metaplane's $13.8M Series A&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/posts/kevinzenghu_dataengineering-dataquality-dataobservability-activity-7170814269066887168-WpFs?utm_source=share&amp;amp;utm_medium=member_desktop"&gt;&lt;strong&gt;CEO &amp;amp; Co-Founder, Kevin Hu's, LinkedIn Announcement&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today I’m happy to announce our Series A led by Felicis Ventures with participation from existing investors Khosla Ventures, Y Combinator, Flybridge Capital Partners, Stage 2 Capital, along with new investors B37 Ventures. We’re also welcoming Javier Soltero, the SVP &amp;amp; GM of Canva Enterprise, previously the VP &amp;amp; GM of Google Workspace and a two-time founder, to the board.&lt;/p&gt;

&lt;p&gt;Following 6x growth in the past year, this Series A investment brings our total amount raised to $22.2M. Most importantly, it’s consistent with our company principle of raising the right amount of money at the right time at the right valuation. This way, we make sure the success of our company is aligned with our customers’ success.&lt;/p&gt;

&lt;p&gt;Since our &lt;a href="https://www.metaplane.dev/blog/the-next-stage-of-metaplane"&gt;previous fundraise&lt;/a&gt; last year, over 100 companies like Ramp, Bose, Anduril, and Ro have trusted Metaplane to ensure trust in their data. We are the highest rated &lt;a href="https://www.g2.com/products/metaplane/reviews"&gt;Data Observability product on G2&lt;/a&gt;, with 4.8/5.0 stars across 90+ reviews. And today, I’m happy to share our plans to help 10,000 companies ensure trust in the data that powers their business. But first, we should start from the beginning: why does trust in data matter at all?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9tyqgdn3rqaxzki30v0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9tyqgdn3rqaxzki30v0.png" alt="Image description" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters: Untrusted Data is Worse than Useless
&lt;/h2&gt;

&lt;p&gt;In 2024, the most common method for detecting data issues is still CDT, or Customer-Driven Testing. Customers who are looking at the data notice that something looks wrong, then fire off a Slack message to the data team like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Is this dashboard broken?”&lt;/li&gt;
&lt;li&gt;“Why does this number seem off?”&lt;/li&gt;
&lt;li&gt;“Why aren’t these accounts up-to-date?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Time and trust – the two things that are easy to lose and hard to regain – are lost. The investments of data teams start to get undermined. Companies slowly lose confidence in data, and as a result, lose their ability to build competitive advantage from one of their truly unique and defensible assets. Trusted data is the foundation on which companies progress from business intelligence to automation to generative AI.&lt;/p&gt;

&lt;p&gt;The downward spiral happens for two reasons. The first reason is &lt;strong&gt;asymmetry&lt;/strong&gt;. While data teams are responsible for hundreds or thousands of data assets across fragmented systems, the consumers of data care most about the number that they’re currently looking at. The second reason is &lt;strong&gt;entropy&lt;/strong&gt;. The surface area of data maintained by the data team tends to grow, leading to more opportunities for breakage. These two forces trigger a vicious cycle in which maintaining trust in data feels like a Sisyphean task of pushing a boulder up a hill.&lt;/p&gt;

&lt;p&gt;Metaplane was founded to provide leverage in this fight against asymmetry and entropy. Using automations on top of metadata, our hope is that data work in 2034 will feel less like “working in the dark” and more like software engineering work. Issues still happen, but engineering teams have tools like Datadog and Splunk to help prevent, anticipate, and resolve them. Vicious cycles give way to virtuous cycles of increasing trust and reliability. &lt;/p&gt;

&lt;p&gt;We’re already seeing the influence of engineering best practices in the work of moving, transforming, and using data. Now is the time to see maturation in the higher level governance problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We’re Building: The Next Tier of the Tech Tree
&lt;/h2&gt;

&lt;p&gt;Metaplane is already at the forefront of what is possible in data observability. Last year we said we would extend data quality from detection to prevention, expand integrations, and expand data observability from monitoring quality to usage and spend. We did all of that and more over the course of &lt;a href="https://www.metaplane.dev/blog/category/changelog"&gt;50+ product launches&lt;/a&gt; in the past year, which were made possible by working closely with our customers while laying robust foundations.&lt;/p&gt;

&lt;p&gt;The end result is that data observability became possible. Now, we want data observability to feel powerful, but in the way that water is powerful. Data observability should mold itself around the needs of your organization. It should be soft when we need light requirements, and heavy when we have critical workloads. And when it works, it’s like it’s hardly even there.&lt;/p&gt;

&lt;p&gt;We think this next era of data observability as powerful will rest on three key pillars:&lt;/p&gt;

&lt;h3&gt;
  
  
  Observe Everything
&lt;/h3&gt;

&lt;p&gt;Especially when it comes to data, anything that can go wrong, will go wrong. Worse: data is so interconnected that there are cascading effects, such that the root cause of an issue in one corner could be something completely unexpected in another corner.&lt;/p&gt;

&lt;p&gt;That’s why every piece of metadata counts (especially if your product is named after the “metadata plane”). Metaplane was already the first data observability tool to launch integrations with transactional databases, ETL tools like Fivetran, and reverse ETL tools like Hightouch and Census.&lt;/p&gt;

&lt;p&gt;But what about upstream issues like unsanitized inputs in a CRM or a faulty migration in your application DB? Or dashboards that suddenly go unused, or spiking query times? Every single piece of telemetry emitted by your data systems should be observed, stored, centralized, and monitored with the proper architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automated Monitoring Architecture
&lt;/h3&gt;

&lt;p&gt;We define a monitoring architecture as the design decisions that determine what you monitor, alongside how and when you monitor it. Just like data architectures, monitoring architectures should reflect and anticipate the needs and evolution of the business.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm11wwmkdxvegqmzf0bl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm11wwmkdxvegqmzf0bl.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Specifically, this “inverted pyramid” architecture is frequently the optimal trade-off between signal and noise, coverage and cost, and centralization and context. Ideally, this architecture is expressed on the semantic level through constraints like “give me all tables two layers upstream of a Tableau worksheet used by our VP of Marketing” or “show me all Fivetran landing zones that have been delayed in the past month.”&lt;/p&gt;

&lt;p&gt;By combining metadata from your data stack alongside these semantic filters, Metaplane should help you implement and maintain this architecture automatically by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trust Everywhere
&lt;/h3&gt;

&lt;p&gt;Achieving 100% trustworthy data is a Sisyphean task, like pushing a boulder up a hill. But the goal isn’t to have perfect data. The goal is to get as much value out of data as possible, which means knowing how trustworthy it is given a business goal.&lt;/p&gt;

&lt;p&gt;Customer-Driven Testing is not a tenable solution. Neither is continually refreshing an open tab. Given that reality, the trustworthiness of data should be like a label on data where and when it is used. If that data is consumed in a dashboard, there should be a red/yellow/green status check. If it’s consumed in a web application, there should be a Chrome extension. If it’s consumed in an Airflow job, there should be an API to retrieve the status of underlying tables.&lt;/p&gt;

&lt;p&gt;By observing everything and maintaining an optimal alerting architecture on top, the last mile is to make sure that data is trusted at the time of consumption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building on Solid Foundations
&lt;/h3&gt;

&lt;p&gt;If you already use Metaplane, you’ve probably used features that are part of those big pillars. Progress is well underway. But rest assured, all progress we make comes hand-in-hand with investing in what got us here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Metadata extraction&lt;/strong&gt; from the tools you use most, including column-level lineage parsing from query history and deep integrations with BI tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain-specific machine learning&lt;/strong&gt; that is tailored to the unique patterns of your business, to ensure every alert is helpful and to avoid dreaded alert fatigue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrated experiences&lt;/strong&gt; that are easy to get started with (you can connect to Metaplane in less than 30 minutes without talking to a salesperson), easy to get value from, and deeply blend together metadata so that you get what you want, when you want it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How We Get There: Iron sharpens iron
&lt;/h2&gt;

&lt;p&gt;Our Series A comes with expectations for growth. And of course we’re investing in go-to-market to educate the market and provide great human experiences for our customers. But the primary way we invest in growth is by continuing to invest in building the best product.&lt;/p&gt;

&lt;p&gt;We build the best product by being the best partners to our customers. The future of data observability is yet to be built, but the problems that it solves exist today.&lt;/p&gt;

&lt;p&gt;Learning from legendary partnerships like that between Uber and Twilio, our approach is to partner closely with the companies that live in the future. These forward-thinking companies bring in Metaplane to solve a problem. But because every company is unique, they stretch Metaplane to solve their problem. We look at the ways in which the product is stretched, combine it with feedback, then solidify it into a real product. &lt;/p&gt;

&lt;p&gt;Almost every feature we have has been co-developed with a customer: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After ClickUp asked for lineage down to Reverse ETL tools, Todd and Jen built our Hightouch and Census integrations within two days. &lt;/li&gt;
&lt;li&gt;Colby worked with CarGurus to add visualizations of circular references to our lineage map. &lt;/li&gt;
&lt;li&gt;Our public-facing API was developed together with Klaviyo, who wanted to version control their monitors using Terraform. &lt;/li&gt;
&lt;li&gt;We re-architected high cardinality GROUP BY monitors to meet Bluecore’s scale of 1000s of distinct groups.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Customers often view Metaplane, both the product and people, as extensions of their teams. And that’s exactly how we want it to feel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepoyh29x3b9zfni1wa6b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fepoyh29x3b9zfni1wa6b.png" alt="Image description" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the number of customers depending on Metaplane grows, our commitment is to get even closer to our customer’s needs, building the best possible product for them as quickly as possible. This is the crucible in which the best product is built.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the People Who Believed in Us Look Brilliant
&lt;/h2&gt;

&lt;p&gt;During our fundraise announcement last year, I wrote about a quote from HubSpot co-founder Dharmesh Shah: “Success is making those who believed in you look brilliant.” This year, that is more true than ever. While we’re welcoming new investors, new teammates, new partners, and new customers to the table, we’re devoted to strengthening the relationships that got us here.&lt;/p&gt;

&lt;p&gt;So, thank you to our customers, old and new. Helping you is the reason we exist as a company, and we measure our success by how happy you are. Please keep the feedback coming in our shared Slack channels :).&lt;/p&gt;

&lt;p&gt;Thank you to our new investors Felicis and B37 for trusting us with your time and resources, along with our existing investors at Y Combinator, Flybridge, and SNR for doubling down.&lt;/p&gt;

&lt;p&gt;Thank you to our partners at Snowflake, dbt, Sigma, Brooklyn Data Co, and many other organizations who keep pushing the state-of-the-art in our industry forward.&lt;/p&gt;

&lt;p&gt;Thank you to the team for continually raising the bar, and most of all for building what we’d buy ourselves. With you all, there’s no choice but to enjoy the flight :).&lt;/p&gt;

&lt;p&gt;And to those of you who want to help your company look brilliant by ensuring trust in data, &lt;a href="https://www.metaplane.dev/book-a-demo"&gt;we’d love to chat&lt;/a&gt;. Cheers to a bright future where data is the lifeblood of companies without the teams behind that data getting paged at 3am!&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>dataengineering</category>
      <category>dataobservability</category>
      <category>announcement</category>
    </item>
    <item>
      <title>4 numeric distribution metrics to track in Snowflake (and how to track them)</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Sat, 02 Mar 2024 23:17:57 +0000</pubDate>
      <link>https://dev.to/metaplane/4-numeric-distribution-metrics-to-track-in-snowflake-and-how-to-track-them-41l2</link>
      <guid>https://dev.to/metaplane/4-numeric-distribution-metrics-to-track-in-snowflake-and-how-to-track-them-41l2</guid>
      <description>&lt;p&gt;Everything in your business runs smoothly—until it doesn’t. Out of nowhere, sales dip, website traffic plummets, or customer complaints shoot up. And scrambling to figure out what went wrong can feel like a game of business whack-a-mole.&lt;/p&gt;

&lt;p&gt;Ultimately, when you react to problems as they pop up, you spend time and resources that would be better allocated elsewhere. If only you knew what issues were headed your way before they actually hit…&lt;/p&gt;

&lt;p&gt;This is where tracking numeric data comes into play. By monitoring 4 key metrics in your Snowflake data warehouse, you can uncover hidden patterns, predict upcoming trends, and make decisions based on solid data, not just gut feelings.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll walk you through which numeric data metrics you need to be tracking and how to track them in Snowflake.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Numeric Data?
&lt;/h2&gt;

&lt;p&gt;Numeric data is simply measurable information. It’s a fundamental component of statistics, often shown by its distribution (i.e. the shape or pattern of the data) in the form of a histogram.&lt;/p&gt;

&lt;p&gt;While visual methods are great for human eyes to see and understand, sometimes we need to describe data patterns in terms of numbers. For instance, in the context of data observability, when we use machine learning to alert on anomalies within our numeric data.&lt;/p&gt;

&lt;p&gt;For that, we rely on 4 standard metrics to summarize these distributions: minimum, maximum, mean, and standard deviation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimum (min): This is the smallest number in your data set.&lt;/li&gt;
&lt;li&gt;Maximum (max): This is the largest number in your data set. &lt;/li&gt;
&lt;li&gt;Mean: Often referred to as the average, this is calculated by adding all the numeric values together and dividing by the number of values. It gives a central value for the data.‍&lt;/li&gt;
&lt;li&gt;Standard deviation:  This is the amount of variation or dispersion in a set of values. A low standard deviation means that the values tend to be close to the mean, while a high standard deviation indicates that the values are spread out over a wider range.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we’ll take a deeper look at each metric, and using sample SQL queries, we’ll show you how to track them in Snowflake. For context, the sample queries below follow an e-commerce site. They assume that you have a 'sales' table that records your online store's daily revenue, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fave45ygalzwkr1258out.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fave45ygalzwkr1258out.png" alt="Image description" width="459" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This ‘sales’ table includes two columns: 'amount', which shows the daily earnings, and 'date', which indicates the day of these earnings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minimum
&lt;/h3&gt;

&lt;p&gt;The minimum is the smallest value within a data set. So, if you have a data set representing daily sales, the minimum would be the lowest sales amount recorded on any given day.&lt;/p&gt;

&lt;p&gt;While it’s often easy to overlook low sales figures when they’re overshadowed by high-performing days, the minimum can be a major indicator of your business's health during its quietest periods. Understanding the context of the lowest sales you have on any given day can reveal the underlying stability and consistency of your business.&lt;/p&gt;

&lt;p&gt;Take this e-commerce example, for instance:&lt;/p&gt;

&lt;p&gt;As the owner of an online store, you maintain a Snowflake dashboard with a graph showing the store's daily sales over the past six months. But over the past few months, you’ve noticed a concerning trend in this graph. While your peak sales days, typically around new product launches or holiday seasons, are doing well, there's a noticeable decline in the minimum daily sales.&lt;/p&gt;

&lt;p&gt;This trend of decreasing minimum daily sales is a red flag. It could mean several things:&lt;/p&gt;

&lt;p&gt;There's an issue with the website's user experience on off-peak days. This could be due to various factors such as poor website navigation, technical glitches, or less compelling content during these periods.&lt;/p&gt;

&lt;p&gt;A new competitor has entered the market. A drop in the lowest sales figures could be a sign that customers are choosing to spend their money elsewhere. Tracking the minimum sales can be an early indicator of losing market share to competitors.&lt;br&gt;
Customer preferences are changing. It might mean that your product range is no longer aligning with current market trends or customer interests. This decline could prompt a review of your product offerings and marketing strategies to ensure they align with evolving customer preferences.&lt;/p&gt;

&lt;p&gt;There are issues with inventory. Customers unable to find what they need might turn to other sources, leading to reduced sales. You might need to reassess your inventory management to guarantee that popular products are always in stock.&lt;/p&gt;

&lt;p&gt;Tracking this minimum daily sales figure gives you an early warning, so you can dig deeper into the root cause of the issue. Here’s how this command looks in Snowflake, assuming you have a sales table similar to the one above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT MIN(amount) AS MinDailySales
FROM sales;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Maximum
&lt;/h3&gt;

&lt;p&gt;The maximum is the largest value within a data set. Juxtaposing the minimum definition above, if you have a data set representing daily sales, the maximum would be the highest sales amount recorded on any given day.&lt;/p&gt;

&lt;p&gt;These high points can often be linked to specific actions you took, like a great marketing campaign or a popular product launch. So, tracking them means you can figure out what's working really well (and try to do it again). It also helps you with planning: making sure you have enough products in stock, enough people working, and that your website can handle a lot of visitors, all without spending too much when it's not necessary.&lt;/p&gt;

&lt;p&gt;Let’s revisit our e-commerce example:&lt;/p&gt;

&lt;p&gt;On the Snowflake dashboard that you've been using to track your daily sales over the past six months, there's also a graph showing the days when sales peaked. Seeing an upward trend in these peak sales days is usually a great sign. More often than not, it suggests that your recent marketing strategies are hitting the mark and there's a high demand for what you're selling.&lt;/p&gt;

&lt;p&gt;But before you celebrate, verify that these numbers are accurate and not skewed by data recording errors, like incorrect transaction logging. You want to be certain that this upward trend is genuine.&lt;/p&gt;

&lt;p&gt;Once you've verified the accuracy of your data and you're confident that these peak sales figures are, in fact, real, this success leads to a set of new questions and considerations. For instance, can your website handle the increased traffic on these busy days? You don't want the site crashing or slowing down just when customer interest is at its peak. Also, think about your inventory. Can you keep up with this higher demand without ending up with too much stock afterward?&lt;/p&gt;

&lt;p&gt;At the end of the day, the benefit of tracking the maximum metric is twofold—you validate the effectiveness of your marketing and product strategies and ensure the robustness/reliability of your operations. Here’s how this command looks in Snowflake, assuming you have a sales table similar to the one above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT MAX(amount) AS MaxDailySales
FROM sales;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mean
&lt;/h3&gt;

&lt;p&gt;The mean is the average of all your data. While you might have days with exceptional sales due to a product launch and days with very low sales, the mean helps you understand your typical performance. It smooths out the extreme highs and lows, giving you a balanced view of your overall performance and business health.&lt;/p&gt;

&lt;p&gt;This metric is especially important in planning and setting realistic expectations. If you're only focusing on the high points, you might overestimate your performance. And if you're only looking at the lows, you might underestimate it.&lt;/p&gt;

&lt;p&gt;Now, back to our e-commerce example:&lt;/p&gt;

&lt;p&gt;Right next to your min and max graphs in your Snowflake dashboard, you also have a graph of average daily sales. Like tracking your maximum, you want to see an upward trend. In this case, though, we’re looking for a steady rise.&lt;/p&gt;

&lt;p&gt;A steady sales growth rate is a good indicator that overall business is growing, reflecting not just occasional spikes from big events but consistent growth across regular days as well. It suggests that your strategies—be it marketing, customer engagement, or inventory management—are resonating with your customers.&lt;/p&gt;

&lt;p&gt;On the flip side, seeing a steady decline in sales would indicate that your strategies are not resonating with your customers. In this case, you’ll need to revisit all your strategies to find what’s not resonating, and pivot accordingly.&lt;/p&gt;

&lt;p&gt;Either way, tracking your mean distribution over time helps identify gradual changes in business performance, ensuring that true growth (or decline) isn’t masked by high-variation days. Here’s how this command looks in Snowflake, assuming you have a sales table similar to the one above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT AVG(amount) AS AvgDailySales
FROM sales;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Standard deviation
&lt;/h3&gt;

&lt;p&gt;The standard deviation is the amount of variation or dispersion in a set of values. It’s a measure of how consistent or inconsistent your numbers are. A small standard deviation means your sales numbers are pretty close to each other most of the time—which is good because it tends to make your business more predictable.&lt;/p&gt;

&lt;p&gt;A large standard deviation, on the other hand, means your data is highly inconsistent, and it’s usually a sign that there are factors affecting your business that you need to understand.&lt;/p&gt;

&lt;p&gt;Let’s go back to our e-commerce example one last time:&lt;/p&gt;

&lt;p&gt;Next to your min, max, and mean graphs in your Snowflake dashboard is also a graph of standard deviation. If you start noticing fluctuations in your sales patterns. To understand this better, you can focus on the standard deviation of daily sales.&lt;/p&gt;

&lt;p&gt;For instance, for a big product launch, you’ll probably notice a huge spike in sales, resulting in a high standard deviation for that period. This might indicate that your marketing campaign for this launch was effective. But if that spike is followed by several days of significantly lower sales, you’ll see this pattern of high sales followed by low sales days will cause your standard deviation to increase.&lt;/p&gt;

&lt;p&gt;If your goal is to smooth out these fluctuations, you might need to rethink your marketing approach to not just create a buzz around new launches but also to maintain steady sales afterward.&lt;/p&gt;

&lt;p&gt;And by tracking the standard deviation in your Snowflake sales data, you can gauge how well your revised marketing approaches are working towards achieving more consistent sales, and adjust your strategies accordingly for better business stability and predictability. Here’s how this command looks in Snowflake, assuming you have a sales table similar to the one above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT STDDEV(amount) AS StdDevDailySales
FROM sales;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Useful conditional statements for numeric data functions in Snowflake
&lt;/h2&gt;

&lt;p&gt;Now that we’ve covered the basics, you can also refine your functions using conditional statements. For instance, if you want to focus on a specific time frame, such as a particular month, you can use a WHERE clause. Here’s what that looks like in Snowflake.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT AVG(amount) AS AvgDailySales
FROM sales
WHERE date &amp;gt;= '2024-01-01'
AND date &amp;lt; '2024-02-01';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Snowflake also supports window functions, which can be useful if you want to calculate these metrics over different partitions of your data (i.e. per month or per product category). Here's an example of how you could calculate the average daily sales per month:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
SELECT 
  DATE_TRUNC('MONTH', date) AS Month, 
  AVG(amount) AS AvgMonthlySales
FROM sales
  GROUP BY DATE_TRUNC('MONTH', date);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;For better SQL form, you can condense all these commands into a single SQL query in Snowflake. Here’s how this looks all together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WITH MonthlySalesStats AS (
  SELECT
  DATE_TRUNC('MONTH', date) AS Month,
  MIN(amount) OVER(PARTITION BY DATE_TRUNC('MONTH', date)) AS MinMonthlySales,
  MAX(amount) OVER(PARTITION BY DATE_TRUNC('MONTH', date)) AS MaxMonthlySales,
  AVG(amount) OVER(PARTITION BY DATE_TRUNC('MONTH', date)) AS AvgMonthlySales,
  STDDEV(amount) OVER(PARTITION BY DATE_TRUNC('MONTH', date)) AS StdDevMonthlySales
FROM sales
WHERE date &amp;gt;= '2024-01-01' AND date &amp;lt; '2024-07-01' -- Specifying the time frame for the first half of 2024
)
SELECT DISTINCT Month,
  MinMonthlySales,
  MaxMonthlySales,
  AvgMonthlySales,
  StdDevMonthlySales
FROM MonthlySalesStats
ORDER BY Month;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;DATE_TRUNC('MONTH', date)&lt;/code&gt; function is used to group sales by month.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;OVER(PARTITION BY DATE_TRUNC('MONTH', date))&lt;/code&gt; clause with each aggregate function calculates the min, max, average, and standard deviation for each month within the specified date range.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;WHERE&lt;/code&gt; clause limits the data to the first half of 2024 (from January 1, 2024, to June 30, 2024).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;SELECT DISTINCT&lt;/code&gt; statement ensures that each month is listed only once along with its corresponding sales statistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you a complete monthly breakdown of the minimum, maximum, average, and standard deviation of sales for each month in the specified time frame, so you can track sales performance trends over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;In a perfect world, you could sense when there’s a hint of change in the air—especially when those sudden shifts could balloon into larger business problems. But while that sixth sense might not exist, tracking your numeric distribution metrics gives you a proactive leg up.&lt;/p&gt;

&lt;p&gt;When you track the min, max, mean, and standard deviation in Snowflake, you can pick up on business-changing patterns and trends. That way, you can act fast, fix small issues before they become big headaches, and even capitalize on opportunities as they arise—all because you have the full picture of your data.&lt;/p&gt;

&lt;p&gt;Want to track your numeric data in Snowflake tables and views within minutes, then be alerted on anomalies with machine learning that accounts for trends and seasonality? &lt;a href="https://www.metaplane.dev/signup"&gt;Get started &lt;/a&gt; with Metaplane for free or &lt;a href="https://www.metaplane.dev/talk-to-us"&gt;book a demo&lt;/a&gt; to learn more.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>snowflake</category>
      <category>dataengineering</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Detecting table insert misses with adaptive flatline alerts</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Sat, 02 Mar 2024 23:12:21 +0000</pubDate>
      <link>https://dev.to/metaplane/detecting-table-insert-misses-with-adaptive-flatline-alerts-3o3b</link>
      <guid>https://dev.to/metaplane/detecting-table-insert-misses-with-adaptive-flatline-alerts-3o3b</guid>
      <description>&lt;p&gt;Have you tried building tests or ML models to detect anomalies in your data warehouse? Turns out it’s ridiculously hard! &lt;/p&gt;

&lt;p&gt;For example, say you have a table storing ingested 3rd-party data, which should keep getting new rows every day. You want to know if it stops growing, but how long should you wait for new data to be loaded before you get an alert? It’s a delicate balance. You definitely want to know as soon as possible that data aren’t loading, but you also don’t want to cause panic every time there’s a small delay.&lt;/p&gt;

&lt;p&gt;But maybe you have to try this—despite the headache—because an API change caused your data to stop loading, and nobody knew for a week. Or a transformation job failed to run on schedule. Or maybe an application broke, nights were spent backfilling data, and you swore to never let it happen again.&lt;/p&gt;

&lt;p&gt;Whatever the reason, this is how you can set up adaptive flatline alerts for proactive monitoring in your data systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step function modeling
&lt;/h2&gt;

&lt;p&gt;Let’s say you’ve set up a test to check the count of rows in an important table with ingested data. Your test probably has a few characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run it on a regular interval (maybe hourly)&lt;/li&gt;
&lt;li&gt;You usually get the same value over and over when the table isn’t changing, but then it jumps to a new plateau after an insert (maybe daily)&lt;/li&gt;
&lt;li&gt;There is some variation in the size and timing of the table changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of these characteristics, your row counts follow an irregular step function, which means your model needs to account for both the increases and the flatlines. So, when there’s a change your model checks that it’s not too big, and when there’s a plateau your model checks that it’s not extending too long. &lt;/p&gt;

&lt;p&gt;At this point, your model might look like the graph below. The blue lines are your row count values sampled at various points throughout the day, and the orange bounds are the acceptable ranges for the increases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv159zrlyrjtutkx0bhbi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv159zrlyrjtutkx0bhbi.png" alt="Image description" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how on November 27th, on the right side of the graph, the row count values flatline? This is where the logic needs to kick in to say “Hey, this table usually gets a daily insert but nothing’s happening—help!” &lt;/p&gt;

&lt;h2&gt;
  
  
  Flatline buffer
&lt;/h2&gt;

&lt;p&gt;But maybe you don’t want to get an alert immediately after the 24th hour with no increase. Maybe the insert and the test run at the same time, and the test just happens to run before the insert is complete. Or maybe there’s some variance in the timing of the insert. Either way, you probably want the model to wait at least one hour to confirm that there’s really a problem before an alert yanks you out of your flow. &lt;/p&gt;

&lt;p&gt;So, you establish some buffer time, either manually or with a model that learns the right amount of buffer to set. Because each table behaves differently and has different levels of importance for your data pipelines, you’ll want different buffers per table. Below is an example of a trend-based buffer, which uses the average historical trend (orange line) to determine how soon to alert:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7ni77b3qve991fcf0wg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7ni77b3qve991fcf0wg.png" alt="Image description" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See how the row count value (blue) has stayed flat but the model (orange line) is projecting that the row count should have increased after 24 hours? This is where you can look to determine how much buffer you want. As long as the value stays within the prediction bounds (orange area), no alert will trigger. &lt;/p&gt;

&lt;p&gt;At Metaplane, we have two options for you to tune this buffer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.metaplane.dev/docs/configuring-monitors#sensitivity"&gt;Sensitivity&lt;/a&gt;: Increasing sensitivity would raise the lower bound so the alert would sound sooner.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.metaplane.dev/docs/providing-model-feedback"&gt;Mark as normal&lt;/a&gt;: If the model alerts too soon you can mark the flatline as normal with a click, and the model will learn to wait longer to alert during flatlines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Navigating the fine line between staying informed and being overwhelmed by alerts is an art, especially with high-stakes data integrity issues. So, we invite you to compare your alerting results to our ML-based anomaly detection! &lt;/p&gt;

&lt;p&gt;Metaplane’s flatline detection algorithm learns about your data over time, tailoring itself to be more meaningful and actionable for your context. Go on, put it to the test! &lt;a href="https://metaplane.dev/signup"&gt;Create an account&lt;/a&gt; and get set up within 30 minutes today.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>sql</category>
      <category>todayilearned</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Three ways to track schema drift in Snowflake</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Sat, 02 Mar 2024 23:07:32 +0000</pubDate>
      <link>https://dev.to/metaplane/three-ways-to-track-schema-drift-in-snowflake-5a9i</link>
      <guid>https://dev.to/metaplane/three-ways-to-track-schema-drift-in-snowflake-5a9i</guid>
      <description>&lt;p&gt;Changes in database schema over time—whether that’s additions, deletions, or modifications of columns, tables, or data types—lead to schema drift. These changes can be planned or unplanned, gradual or unexpected. &lt;/p&gt;

&lt;p&gt;These are some of the common causes of schema drift:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data gets corrupted during migration&lt;/li&gt;
&lt;li&gt;Data warehouse updates such as:&lt;/li&gt;
&lt;li&gt;Adding features or fixing issues&lt;/li&gt;
&lt;li&gt;Establishing new relationships between tables&lt;/li&gt;
&lt;li&gt;Removing existing relationships between tables when they become unnecessary or irrelevant&lt;/li&gt;
&lt;li&gt;Your organization switches to a different data warehouse&lt;/li&gt;
&lt;li&gt;Your organization’s business requirements change and you need to:&lt;/li&gt;
&lt;li&gt;Add new fields for new types of data to be collected and stored&lt;/li&gt;
&lt;li&gt;Remove fields if certain types of data are no longer needed&lt;/li&gt;
&lt;li&gt;Modify the data type of a field to reflect the nature of the data being stored correctly&lt;/li&gt;
&lt;li&gt;You introduce new data sources&lt;/li&gt;
&lt;li&gt;Technology standards change and/or new regulations are introduced&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all those causes, it’s no wonder that schema drift leads to so many data pipeline outages. You've got columns being added, data types changing on the fly, and when they go unnoticed, they swiftly erode data quality. &lt;/p&gt;

&lt;p&gt;This results in missing or inconsistent data that not only compromises the integrity and reliability of your queries and reports but also diminishes the overall trust in data across the organization. To mitigate this, you have to track any and all possible schema changes. Here are three ways to track schema drift in Snowflake.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: Generate and compare schema snapshots
&lt;/h2&gt;

&lt;p&gt;Snowflake and other cloud warehouses’ support for native Schema Change Tracking is still in its infancy, but that doesn’t preclude users from creating their own history of changes. &lt;/p&gt;

&lt;p&gt;One way that you can do this is through periodic, recurring snapshots of your schemas. Here’s a simple sample query that you could run to snapshot this for table(s) within a given database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use DATABASE 
With snapshot_t0 as
(
Select
  table_schema,
  Table_name,
  Column_name,
  Data_type
From information_schema.columns
Order by 1,2,3,4
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you create that snapshot, you’ll want to compare for deltas. Imagining we’re staying with just SQL, you’ll then write a few queries to check for common schema changes. Below are sample queries with snapshot_t0 and snapshot_t1 being placeholder names for your snapshot tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; --- Make sure to either name your snapshot tables with different column names or specify them here. 
With schema_comparison as
(
Select *
From snapshot_t0
Join snapshot_t1 on snapshot_t0.table_schema = snapshot_t1.table_schema
)

--- Finding new, dropped, or renamed columns
Select
 Column_names_0,
 Column_names_1
From schema_comparison
Where column_names_0 != column_names_1

--- Finding new, dropped, or renamed tables
Select
 table_names_0,
 table_names_1
From schema_comparison
Where table_names_0 != table_names_1

--- Finding new, dropped, or renamed data types
Select
 table_names_0,
 table_names_1
From schema_comparison
Where 
 column_names_0 = 
 &amp;amp; column_names_1 = 
 &amp;amp; data_type_0 != data_type_1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a few gaps in this approach, with significant outliers being:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The need to specify which database(s) and schema(s) you’d like to run this for&lt;/li&gt;
&lt;li&gt;Orchestration to schedule both snapshots and deltas&lt;/li&gt;
&lt;li&gt;An understanding of whether a schema change was significant&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Option 2: Snowflake Community Python script
&lt;/h2&gt;

&lt;p&gt;Inspired by the &lt;a href="https://flywaydb.org/"&gt;Flyway database migration tool&lt;/a&gt;, the &lt;a href="https://github.com/Snowflake-Labs/schemachange/blob/master/schemachange/cli.py"&gt;Snowflake Community python script&lt;/a&gt; (&lt;code&gt;schemachange&lt;/code&gt;) is a simple Python-based tool to manage all of your Snowflake objects. You can read all about the &lt;a href="https://github.com/Snowflake-Labs/schemachange"&gt;open-source script here&lt;/a&gt;, but here’s an overview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You or someone on your team should have the ability to run Python. Note that you’ll need the ‎&lt;a href="https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-install"&gt;Snowflake Python driver&lt;/a&gt; installed wherever you’ll be running this script. You’ll also want to familiarize yourselves with Jinja templating if you want to simplify inserting variables as you find yourself with new tables.&lt;/li&gt;
&lt;li&gt;You’ll need to create a table in Snowflake to write changes to, with the default location being: &lt;code&gt;METADATA.SCHEMACHANGE.CHANGE_HISTORY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You’ll need to specify your Snowflake connection parameters in &lt;code&gt;schemachange-config.yml&lt;/code&gt;
You’ll need to write queries that output your desired schemas to compare, following their &lt;a href="https://github.com/Snowflake-Labs/schemachange/tree/master?tab=readme-ov-file#change-scripts"&gt;naming conventions&lt;/a&gt;, structured in &lt;a href="https://github.com/Snowflake-Labs/schemachange/tree/master?tab=readme-ov-file#project-structure"&gt;this way&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This script helps you manually track all of your schema changes. But you’ll also need to explicitly define what tables, schemas, and databases you're tracking—and be able to run Python and be familiar with the CLI to do so. &lt;/p&gt;

&lt;h2&gt;
  
  
  Option 3: Leverage Snowflake’s information_schema
&lt;/h2&gt;

&lt;p&gt;Similar to Option 2, you can leverage Snowflake’s information_schema to get a full view of all schema changes. This solution can be helpful for ad-hoc checks when triaging a data quality incident. But keep in mind that, by default, Snowflake only retains this information for 7 days. &lt;/p&gt;

&lt;p&gt;An example query for the full list of schema changes would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
 database_name, 
 schema_name,
 query_text
FROM table(information_schema.query_history())
WHERE
---specify schema change query(s) here
 query_text LIKE ‘ALTER TABLE%’
AND
---optional specification for database_name, schema_name, user or compute warehouse here
---alternatively, you can query the information_schema.query_history_by* tables
(
 Database_name = ‘’
 schema_name = ‘’
 role_name = ‘‘
 user_name = ‘’
 warehouse_name = ‘’
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a great option for triaging incidents that occurred within the past week. You can optionally save the results for a full history of schema changes to reference, but it can quickly become compute-heavy for Snowflake instances with a high volume of queries. &lt;/p&gt;

&lt;p&gt;So, if none of these options quite fit the bill and you’re looking for an automated way to track your schema changes, we have another option.&lt;/p&gt;

&lt;p&gt;Metaplane automatically monitors your data warehouse for schema changes (e.g. column additions, data type changes, table drops, etc). There’s no need to define what tables, schemas, and databases you're tracking.&lt;/p&gt;

&lt;p&gt;The best part? With Metaplane, you can filter out which schema changes you want to monitor and receive notifications about. That way, you can only receive the alerts that are critical to your data's integrity and operational continuity—not just a barrage of noise.&lt;/p&gt;

&lt;p&gt;Whether you opt for a manual or an automated approach, the bottom line is this: start tracking your schema changes if you aren’t already. So, choose a method and stick with it! That’s the only way to prevent any more schema drift-related pain, increase the reliability of your data systems, and boost trust across the organization in the process. &lt;/p&gt;

&lt;p&gt;Want to get automatically alerted on schema changes? &lt;a href="https://www.metaplane.dev/book-a-demo"&gt;Talk to us&lt;/a&gt; or start a &lt;a href="https://metaplane.dev/signup"&gt;free trial&lt;/a&gt; today.&lt;/p&gt;

</description>
      <category>schemadrift</category>
      <category>sql</category>
      <category>snowflake</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Comparing Snowflake Dynamic Tables with dbt</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 01 Mar 2024 20:15:59 +0000</pubDate>
      <link>https://dev.to/metaplane/comparing-snowflake-dynamic-tables-with-dbt-1dcc</link>
      <guid>https://dev.to/metaplane/comparing-snowflake-dynamic-tables-with-dbt-1dcc</guid>
      <description>&lt;p&gt;Snowflake is one of the most popular data lakehouses today - and for good reason; they not only made it extremely easy to manage the infrastructure traditionally associated with data warehouses, such as scaling storage and compute, but continue to push the envelope, with new features such as Dynamic Tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Snowflake Dynamic Tables?
&lt;/h2&gt;

&lt;p&gt;Dynamic tables are a new type of table in Snowflake, created from other existing objects upstream, that update (i.e. re-run its query) when its parent table(s)’ update. This is useful for any sort of modeling where you intend on reusing the results, and need the data to be current. The image below, taken from Snowflake’s documentation, is a simplified overview of how Dynamic Tables are created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfx73jkli8em3a04a6gu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfx73jkli8em3a04a6gu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The “automated refresh process” natively refreshes on fixed intervals (i.e. x number of minutes, y number of hours, etc) rather than specific times of the day. A workaround with tasks can be used if you wish to use a cron schedule instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is dbt?
&lt;/h2&gt;

&lt;p&gt;dbt is one of the most popular frameworks today for transformations (i.e. modeling), in part, due to its ability to increase accessibility and collaboration in modeling through features such as SQL-based modeling and a centralized code repository with a history of documentation. Two core parts of dbt include:&lt;/p&gt;

&lt;p&gt;A profile configuration file (in YAML) - here is where you’ll specify how and which data warehouse you’ll be connecting to&lt;br&gt;
Model logic (i.e. sql files) - a collection of reusable queries (i.e. models) that you intend on reusing.&lt;br&gt;
Note that the use of dbt is not constrained to Snowflake. A full list of supported integrations can be found here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9a22pznigaoqo9fqbwk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy9a22pznigaoqo9fqbwk.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Snowflake dynamic tables vs dbt
&lt;/h2&gt;

&lt;p&gt;After listening to the Snowflake presentation - my mind immediately leapt to: does this replace dbt? (which is where this article came from). The short answer is “no”. Here’s why:&lt;/p&gt;

&lt;h3&gt;
  
  
  Similarities
&lt;/h3&gt;

&lt;p&gt;Starting with similarities - it’s easy to be confused on the role of Snowflake’s Dynamic Tables in a world where many organizations have already / are looking into implementing dbt for transformations. &lt;/p&gt;

&lt;p&gt;Both Dynamic Tables and dbt will update an “object” in the warehouse based on the results of your query. An exception here is that dbt can create views and (normal) tables in addition to Dynamic Tables.&lt;/p&gt;

&lt;p&gt;The primary modeling language for both are SQL.&lt;br&gt;
Both have some ability to self-reference. dbt models can reference others models, and Dynamic Tables can be created and updated based on other Dynamic Tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Differences
&lt;/h3&gt;

&lt;p&gt;Once we get past the upfront benefit of automating updates to the data fed through models, there are quite a few differences between Snowflake Dynamic Tables and dbt, with a non-exhaustive list of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frequency of updates&lt;/strong&gt;: dbt runs are batched (or micro-batched), which means that models are updated at fixed times throughout the day, whereas Dynamic Tables will update once “source” data is detected to be updated (with a user-configured time lag in place). 
-** Modularity**: dbt model code can be easily reused in other models. Although you can reference Dynamic Tables in your Dynamic Table creation, you’ll create dependencies with the biggest issue likely being time lag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control&lt;/strong&gt;: In part because dbt code is stored in git repositories, users will get the benefit of version control - that is, the ability to enforce code structure validation tests prior to merging the code into production, where the git repository also gives you the added benefit of storing a history of all changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation Rules (Tests)&lt;/strong&gt;: dbt also has a native feature that can be built into model runs, “dbt tests”. These are data validation rules that users specify and can also reuse, much like models, which allows consistency in model outputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lineage + Documentation&lt;/strong&gt;: dbt generates a diagram that shows which objects are referenced in your model, and allows users to define variables, such as the Owner of a model. Both of these features allow for clearer context into what a model is used for(and how to use it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to use Snowflake Dynamic Tables with dbt
&lt;/h2&gt;

&lt;p&gt;In case it’s not clear, if you’re already using dbt - there’s no need to move everything over to Dynamic Tables. If you’re keen on migrating something to take advantage of this new native Snowflake feature, a good candidate would be existing models being run in your Snowflake instance with a combination of Streams + Tasks.&lt;/p&gt;

&lt;p&gt;Shortly after Dynamic Tables entered Preview, dbt released support for Dynamic Table creation (&lt;em&gt;Note: you must be viewing docs for dbt v1.6 to see the section. Scroll to the top of the docs to set your version number&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;This is amazing because it effectively gives you the best of both worlds all of the benefits of a git environment for your modeling code (e.g. version control), built-in lineage and documentation, AND updates to models automatically triggered by refreshed data (independent of the schedule in your profile.yml).&lt;/p&gt;

&lt;p&gt;You likely won’t want to migrate any of the dbt models that you’re currently triggering at a daily or 12 hour cadence, but any dbt runs (and downstream data products) that require near-real-time data would be good candidates for testing Dynamic Table usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upcoming releases for Snowflake’s Dynamic Tables
&lt;/h2&gt;

&lt;p&gt;Dynamic Tables are still fairly new, so we should reasonably expect a few things to change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Expanded dbt support for Dynamic Tables&lt;/strong&gt;: You can track the scope of the changes here, with the first step (dynamic table as a materalization option) already having been implemented within ~2 months.
-** Expanded function support for Dynamic Tables**: One gap right now is the lack of support for a few non-deterministic functions (e.g. CURRENT_DATE()), and the inability to trigger Tasks or Stored Procedures. We’ll likely see support for this over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ecosystem integration improvements&lt;/strong&gt;: One notable callout has been an issue with PowerBI where the list of queryable objects in Snowflake don’t always show all of the Dynamic Tables. Other integrations that don’t currently support Dynamic Tables will likely build in support shortly.
-** Git support**: Take this with a grain of salt, as it seems that the timeline of this release varies depending on who you talk to and when, and there’s no official released scope, but it appears that Snowflake is building support for hosting code (e.g. Snowsight worksheets) in a git repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dynamic Tables Data Quality
&lt;/h2&gt;

&lt;p&gt;Both Snowflake Dynamic Tables and dbt improve automation for your modeling, but have limited support for ensuring data quality when it comes to your data. While dbt tests are a great starting point for validation rules, they fall short when it comes to asynchronous deployment at scale across all of your tables, with one tangible point being a lack of automation for acceptance test thresholds. &lt;/p&gt;

&lt;p&gt;This is where a tool like Metaplane would shine, ensuring data quality for Dynamic Tables (created through dbt or otherwise) and other objects in your Snowflake instance along with alerting on anomalous dbt job durations.&lt;/p&gt;

&lt;p&gt;Data teams at high-growth companies (like Drift, Vendr, and SpotOn) use the Metaplane data observability platform to save engineering time and increase trust in data by understanding when things break, what went wrong, and how to fix it — before an executive messages them about a broken dashboard.&lt;/p&gt;

</description>
      <category>snowflake</category>
      <category>dbt</category>
      <category>dynamictables</category>
      <category>sql</category>
    </item>
    <item>
      <title>Three Ways to Retrieve Row Counts in Redshift Tables and Views</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 01 Mar 2024 20:10:39 +0000</pubDate>
      <link>https://dev.to/metaplane/three-ways-to-retrieve-row-counts-in-redshift-tables-and-views-27f7</link>
      <guid>https://dev.to/metaplane/three-ways-to-retrieve-row-counts-in-redshift-tables-and-views-27f7</guid>
      <description>&lt;p&gt;As your data grows in your Amazon Redshift cluster, it’s important to have an accurate count of the number of rows in your tables or views. You might need this information for capacity planning, performance tuning, or simply to satisfy your curiosity. Fortunately, Redshift provides several methods for retrieving this information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Using the COUNT Function
&lt;/h2&gt;

&lt;p&gt;To count the number of rows in a table or view in Redshift, you can use the built-in COUNT function. Here’s an example SQL snippet that you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT COUNT(*) FROM table_name;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace “table_name” with the name of the table or view that you want to count. This query will return a single row containing the total number of rows in the table or view.&lt;/p&gt;

&lt;p&gt;If you want to track the number of rows over time, you can run this query periodically and store the results in a separate table. Here’s an example SQL snippet that creates a table to store the row counts for a table called “orders”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE row_counts (
    timestamp TIMESTAMP,
    row_count BIGINT
);

INSERT INTO row_counts (timestamp, row_count)
SELECT
    SYSDATE,
    COUNT(*)
FROM
    orders;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code creates a table called &lt;code&gt;row_counts&lt;/code&gt; with two columns: “timestamp” and “row_count”. The “timestamp” column stores the current date and time, while the “row_count” column stores the current row count for the “orders” table. The INSERT INTO statement runs the COUNT query and inserts the result into the “row_counts” table.&lt;/p&gt;

&lt;p&gt;You can then run this code periodically (e.g., daily, hourly) to track changes in the row count over time. Here’s an example SQL snippet that you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSERT INTO row_counts (timestamp, row_count)
SELECT
    SYSDATE,
    COUNT(*)
FROM
    orders;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query inserts a new row into the “row_counts” table with the current date and time and the current row count for the “orders” table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: Using System Statistics
&lt;/h2&gt;

&lt;p&gt;Redshift automatically collects statistics on your tables and views, including row counts, and makes them available in the STL_QUERY and SVV_TABLE_INFO system tables. Here’s an example SQL snippet that you can use to retrieve the row count for a table or view from the SVV_TABLE_INFO table:&lt;/p&gt;

&lt;p&gt;SELECT "rows" FROM SVV_TABLE_INFO WHERE "table"='table_name';&lt;br&gt;
Replace “table_name” with the name of the table or view that you want to count. This query will return a single row containing the total number of rows in the table or view.&lt;/p&gt;

&lt;p&gt;One advantage of using system statistics is that they are updated automatically and don’t require you to run any additional queries or scripts to track the row count. However, keep in mind that system statistics may not always be up-to-date or accurate, especially if you have recently loaded data or made other changes to your table.&lt;/p&gt;

&lt;p&gt;Method 3: Using Multiple Methods&lt;br&gt;
To ensure the accuracy of your row counts, it’s a good practice to use multiple methods to track the number of rows in your tables or views. For example, you might use the COUNT function to get an exact count of the rows in your table, and also use system statistics to get a more approximate count.&lt;/p&gt;

&lt;p&gt;Here’s an example SQL snippet that combines the two methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
    COUNT(*) AS count_exact,
    "rows" AS count_estimate
FROM
    table_name
    JOIN SVV_TABLE_INFO ON "table_name" = "table"
WHERE
    "table" = 'table_name';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Always take into account factors such as table size, frequency of updates, desired accuracy, and associated costs when choosing the method that best fits your specific needs. Each method has its trade-offs, and the best approach depends on your particular situation and needs.&lt;/p&gt;

&lt;p&gt;In the end, understanding and navigating these options will empower you to optimize your Redshift performance and maximize your data analysis capabilities.&lt;/p&gt;

&lt;p&gt;Just remember: extracting row counts is an integral part of managing and understanding your data within Redshift. By choosing the right method tailored to your needs, you can gain insights more quickly, optimize performance, and control costs. With the knowledge and techniques outlined in this article, you are now equipped to navigate the landscape of Redshift row count retrieval effectively and efficiently. Happy querying!&lt;/p&gt;

</description>
      <category>rowcounts</category>
      <category>redshift</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Stay Fresh: Four Ways to Track Update Times for BigQuery Tables and Views</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 01 Mar 2024 20:05:35 +0000</pubDate>
      <link>https://dev.to/metaplane/stay-fresh-four-ways-to-track-update-times-for-bigquery-tables-and-views-2i79</link>
      <guid>https://dev.to/metaplane/stay-fresh-four-ways-to-track-update-times-for-bigquery-tables-and-views-2i79</guid>
      <description>&lt;p&gt;Ever experienced a delayed dashboard? Been frustrated by late data for that critical report? That's the sting of stale data. As a data or analytics engineer, you know how crucial it is to have timely, up-to-date data at your fingertips.&lt;/p&gt;

&lt;p&gt;In this post, we'll explore several ways to determine the "freshness" of your tables and views in Google BigQuery. We'll dive into both relevant SQL queries and metadata via Information Schema to give you multiple tools to keep your data transformations running smoothly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Determining Last Update Time Using the MAX Function
&lt;/h2&gt;

&lt;p&gt;The most straightforward approach to determine the last update time in BigQuery leverages the MAX() function on a timestamp column within your table. This method can be especially useful when your table rows include a timestamp column that gets updated whenever a new record is inserted or an existing one is modified.&lt;/p&gt;

&lt;p&gt;Here's an example of how you can use the MAX() function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
 MAX(timestamp_column) AS last_modified
FROM 
  project_id.dataset.table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this SQL command, replace project_id, dataset, and table with your respective Google Cloud Project ID, BigQuery dataset name, and table name. Also, replace timestamp_column with the name of the timestamp column in your table that records when each row was last updated.&lt;/p&gt;

&lt;p&gt;This command returns the most recent timestamp in the timestamp_column column, which corresponds to the last time any row in the table was updated. This approach gives a precise picture of data freshness at the row level, which can be more informative than just the last time the table schema was updated.&lt;/p&gt;

&lt;p&gt;However, for this method to work, your tables need to have a timestamp column that gets updated with each data modification. If such a column doesn't exist, you might want to consider adding one to your data ingestion pipelines or ETL processes to track row-level updates better.&lt;/p&gt;

&lt;p&gt;Note that this method works on both tables and views, provided the underlying data of the views have a timestamp column that tracks updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Last Modified Time via Metadata
&lt;/h2&gt;

&lt;p&gt;One straightforward approach to find out when a table was last updated in BigQuery is by checking the last_modified_time from the table's metadata. &lt;/p&gt;

&lt;p&gt;You can run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
  table_id, 
  TIMESTAMP_MILLIS(last_modified_time) AS last_modified
FROM 
  project_id.dataset.__TABLES__
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above SQL command, replace project_id with your Google Cloud Project ID and dataset with your BigQuery dataset name. This script returns a list of tables in the specified dataset and their corresponding last modification timestamps. &lt;/p&gt;

&lt;p&gt;_Note that this method only works for tables and not for views, as views in BigQuery do not have a last_modified_time property. _&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracking Updates via INFORMATION_SCHEMA
&lt;/h2&gt;

&lt;p&gt;Google BigQuery also provides an Information Schema, a series of system-generated views that provide metadata about your datasets, tables, and views. &lt;/p&gt;

&lt;p&gt;To retrieve the last update timestamp for both tables and views, you can use the last_change_time column from the INFORMATION_SCHEMA.TABLES view. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
  table_name, 
  TIMESTAMP(last_change_time) AS last_changed
FROM 
  project_id.dataset.INFORMATION_SCHEMA.TABLES
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like before, replace project_id and dataset with your respective project and dataset names. &lt;/p&gt;

&lt;p&gt;However, there's an important caveat to note here. The last_change_time column represents the last time the table schema was updated, not necessarily the data. So, if you only added or removed rows but didn't modify the schema, last_change_time wouldn't reflect those changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Employing Partitioning and Clustering
&lt;/h2&gt;

&lt;p&gt;For a more granular understanding of data freshness, BigQuery's native partitioning and clustering features can be utilized. If your tables are partitioned, you can identify the most recent partition, which often corresponds to the latest data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
  MAX(_PARTITIONTIME) AS last_modified
FROM 
  project_id.dataset.table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember to replace project_id, dataset, and table with your respective details. &lt;/p&gt;

&lt;p&gt;This method is applicable only for partitioned tables, and it won't work for views or non-partitioned tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Google BigQuery provides multiple methods to track the freshness of your data, each with its specific use cases and limitations. It's essential to understand these nuances and select the most appropriate method based on your needs. &lt;/p&gt;

&lt;p&gt;In data-intensive environments where timeliness is of the essence, having these tools at your disposal ensures you can maintain the integrity and reliability of your data.&lt;/p&gt;

&lt;p&gt;Want to track the freshness of BigQuery tables and views within minutes, then be alerted on anomalies with machine learning that accounts for trends and seasonalities? &lt;a href="https://www.metaplane.dev/signup"&gt;Get started&lt;/a&gt; with Metaplane for free or &lt;a href="https://www.metaplane.dev/talk-to-us"&gt;book a demo&lt;/a&gt; to learn more.&lt;/p&gt;

</description>
      <category>freshness</category>
      <category>bigquery</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Stay Fresh: Two Ways to Track Update Times for Snowflake Tables and Views</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 01 Mar 2024 20:02:13 +0000</pubDate>
      <link>https://dev.to/metaplane/stay-fresh-two-ways-to-track-update-times-for-snowflake-tables-and-views-2ade</link>
      <guid>https://dev.to/metaplane/stay-fresh-two-ways-to-track-update-times-for-snowflake-tables-and-views-2ade</guid>
      <description>&lt;p&gt;Ever experienced a delayed dashboard? Been frustrated by late data for that critical report? That's the sting of stale data, or rather, data that isn’t fresh.&lt;/p&gt;

&lt;p&gt;The freshness of a table or view is how frequently it is updated relative to requirements. If a table is expected to be fresh to the hour, but hasn’t been updated in a day, then it is stale. Why is data freshness important? Because inaccurate or outdated information can lead to misguided decisions, muddled forecasting, and even regulatory non-compliance. &lt;/p&gt;

&lt;p&gt;Understanding when your Snowflake table or view was last updated isn't just a nice-to-know—it's a need-to-know. It's about ensuring your data is as fresh as your morning coffee, ready to power your day's insights and actions.&lt;/p&gt;

&lt;p&gt;In this guide, we'll be equipping you with two vital tools in your data freshness arsenal: the MAX function and the LAST_UPDATED column. These are your hammer and screwdriver for ensuring your data is up-to-date and accurate, ready to power the decisions that matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Determining Last Update Time Using the MAX Function
&lt;/h2&gt;

&lt;p&gt;If you have a timestamp column in your Snowflake table, one of the simplest ways to find the most recent update is to use the MAX function. The MAX function returns the maximum value of the specified column. For example, if you have a column named timestamp_column that is updated whenever a row is modified, you can use the following SQL to get the latest update time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT MAX(timestamp_column) AS last_update_time
FROM your_table_name;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Tip: Replace your_table_name with the name of your table, and you'll get the latest timestamp from the timestamp_column column.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This approach works equally well for both tables and views. However, remember that views in Snowflake are essentially saved queries. They don't store data themselves but reflect the data in the underlying tables. Therefore, the freshness of the data in a view is dependent on the freshness of the data in the underlying tables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Two quick notes:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Also note that the precision of the timestamp column used with the MAX function can impact the accuracy of the last update time. If the precision is set to seconds, for example, multiple updates within the same second may not be accurately represented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the MAX function on a large table can be resource-intensive and may impact performance. Consider using partitioning, clustering or materialized views to optimize this operation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Leveraging the LAST_ALTERED Column
&lt;/h2&gt;

&lt;p&gt;What if your table doesn't have a timestamp column? Don't worry, Snowflake has you covered. You can retrieve the last update time from the LAST_ALTERED column in the information_schema.tables or information_schema.views system view.&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT table_name, last_altered
FROM information_schema.tables
WHERE table_schema = 'your_schema' AND table_name = 'your_table_name';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this query, your_schema and your_table_name should be replaced with your schema and table name, respectively.&lt;/p&gt;

&lt;p&gt;This approach provides system-level information, which can be especially useful if your table or view doesn't have a timestamp column. However, there are a couple of things to keep in mind:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The last_altered column reflects the last time the table structure (like adding a new column) was altered, not the last time the data within the table was updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This approach works well for tables, but for views, the last_altered timestamp may not reflect the latest data update time, as it only tracks changes to the view's structure or definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The freshness of a view is contingent upon the underlying tables' data freshness. A view does not hold any data, but instead, it represents the data residing in the base tables.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Understanding the freshness of your data in Snowflake is crucial for accurate and timely data analysis. With the MAX function and the LAST_ALTERED column, you can keep track of the last update time in your tables and views. Just remember that while these methods are robust, they have their nuances. &lt;/p&gt;

&lt;p&gt;Make sure to consider whether you're dealing with a table or a view, and whether you're interested in changes to the data or changes to the structure of the database object. Happy data tracking!&lt;/p&gt;

&lt;p&gt;Want to track the freshness of Snowflake tables and views within minutes, then be alerted on anomalies with machine learning that accounts for trends and seasonalities? Get started with Metaplane for free or book a demo to learn more.&lt;/p&gt;

</description>
      <category>freshness</category>
      <category>snowflake</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Four Efficient Techniques to Retrieve Row Counts in BigQuery Tables and Views</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 01 Mar 2024 19:57:30 +0000</pubDate>
      <link>https://dev.to/metaplane/four-efficient-techniques-to-retrieve-row-counts-in-bigquery-tables-and-views-20h6</link>
      <guid>https://dev.to/metaplane/four-efficient-techniques-to-retrieve-row-counts-in-bigquery-tables-and-views-20h6</guid>
      <description>&lt;p&gt;When interacting with Google's BigQuery, it's often vital to ascertain the number of rows within a table or view. This information serves various purposes such as optimizing performance, analyzing data, and monitoring data flow. &lt;/p&gt;

&lt;p&gt;In this article, we'll explore three dynamic methods to extract row counts in BigQuery, ranging from simple SQL queries using COUNT(*) to harnessing table statistics. We'll also delve into key considerations and potential hurdles for each approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Utilizing COUNT(*)
&lt;/h2&gt;

&lt;p&gt;The COUNT(*) function is the most elementary method to fetch the row count. Although it's a straightforward approach, it can be resource-heavy for larger tables, potentially causing extended execution times and increased costs. Keep in mind that if the table is actively being written to or modified, the row count could change during the query execution, leading to possibly inconsistent results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT COUNT(*) AS row_count
FROM project.dataset.table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method works for views as well as tables because it simply executes the underlying SQL query of the view and counts the results. However, keep in mind that this can be resource-intensive and slow for complex views or those built on top of large tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: Leveraging INFORMATION_SCHEMA
&lt;/h2&gt;

&lt;p&gt;The INFORMATION_SCHEMA provides invaluable metadata about datasets, tables, and views in BigQuery. Querying the TABLES view from this schema is efficient, but it's crucial to remember that the row count fetched from this method is an approximation and may not always be current. BigQuery intermittently updates the row_count field in the INFORMATION_SCHEMA.TABLES, which might not mirror the latest count if the table has been recently modified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
  table_name,
  row_count
FROM 
  project.dataset.INFORMATION_SCHEMA.TABLES
WHERE 
  table_name = 'table'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;_Note that this method will not work for views.&lt;br&gt;
_&lt;/p&gt;
&lt;h2&gt;
  
  
  Method 3: Deploying BigQuery API
&lt;/h2&gt;

&lt;p&gt;By utilizing the BigQuery API, you can programmatically and efficiently retrieve the row count. This method yields accurate results and is immune to potential inconsistencies due to concurrent writes or updates. It's important, however, to ensure you have the necessary access and authentication credentials set up to make API requests. Also, consider that frequent API requests to obtain row counts may introduce additional network overhead and consequentially, increased costs.&lt;/p&gt;

&lt;p&gt;Here's an example using Python and the BigQuery Python client library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from google.cloud import bigquery
‍
client = bigquery.Client()
table_ref = client.dataset('dataset').table('table')
table = client.get_table(table_ref)
row_count = table.num_rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Similar to INFORMATION_SCHEMA, the BigQuery API does not support getting row counts for views directly. The num_rows attribute is only available for tables, not views.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 4: Tapping into BigQuery Table Statistics
&lt;/h2&gt;

&lt;p&gt;BigQuery keeps track of table statistics, including an approximate row count. Using table statistics offers a fast and cost-effective means to estimate the row count without executing a full table scan. Nonetheless, remember that these statistics might not always be up-to-date, particularly if the table has undergone recent modifications. Thus, the row count obtained from table statistics should be viewed as an estimate rather than an exact value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT
  table_id,
  row_count
FROM
  project.dataset.__TABLES__
WHERE
  table_id = 'table'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As with the previous two methods, table statistics are not available for views, so this method will not work either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Determining the row count in BigQuery tables or views is crucial for numerous scenarios. While the COUNT(*) method offers an accurate count, it might be resource-intensive for large tables. On the other hand, methods like INFORMATION_SCHEMA, BigQuery API, or table statistics provide efficient ways to retrieve row counts. &lt;/p&gt;

&lt;p&gt;However, it's essential to acknowledge the potential challenges and limitations inherent in each method. Always take into account factors such as table size, frequency of updates, desired accuracy, and associated costs when choosing the method that best fits your specific needs. &lt;/p&gt;

&lt;p&gt;In the end, understanding and navigating these options will empower you to optimize your BigQuery performance and maximize your data analysis capabilities.&lt;/p&gt;

&lt;p&gt;For instance, for large and infrequently updated datasets, using the INFORMATION_SCHEMA or table statistics could provide a quick and cost-effective solution. Conversely, for smaller tables or datasets that change frequently, the COUNT(*) function might prove to be the most accurate, despite its potential resource intensity. Lastly, if you require programmatic access, the BigQuery API is your go-to solution.&lt;/p&gt;

&lt;p&gt;Remember, each method has its trade-offs, and the best approach depends on your particular situation and needs. For instance, COUNT(*) provides accuracy but may consume more resources, while the BigQuery API ensures consistency but may incur network overhead. INFORMATION_SCHEMA and Table Statistics offer efficiency but may not reflect the most recent changes.&lt;/p&gt;

&lt;p&gt;In conclusion, extracting row counts is an integral part of managing and understanding your data within Google's BigQuery. By choosing the right method tailored to your needs, you can gain insights more quickly, optimize performance, and control costs. With the knowledge and techniques outlined in this article, you are now equipped to navigate the landscape of BigQuery row count retrieval effectively and efficiently. Happy querying!&lt;/p&gt;

</description>
      <category>rowcounts</category>
      <category>bigquery</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Three Ways to Retrieve Row Counts for Snowflake Tables and Views</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 01 Mar 2024 19:53:09 +0000</pubDate>
      <link>https://dev.to/metaplane/three-ways-to-retrieve-row-counts-for-snowflake-tables-and-views-22i</link>
      <guid>https://dev.to/metaplane/three-ways-to-retrieve-row-counts-for-snowflake-tables-and-views-22i</guid>
      <description>&lt;p&gt;Determining the number of rows in a table or view is often essential when working with Snowflake. This information can prove valuable for various purposes, such as performance optimization, data analysis, and monitoring. &lt;/p&gt;

&lt;p&gt;In this article, we will explore different approaches to obtain row counts in Snowflake, ranging from simple SQL queries using &lt;code&gt;COUNT(*)&lt;/code&gt; to leveraging table statistics. We will also highlight essential considerations and provide SQL snippets to ensure correct execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: COUNT(*)
&lt;/h2&gt;

&lt;p&gt;The most straightforward way to retrieve row counts for both tables and views in Snowflake is by using the COUNT(*) function in SQL. This method provides an accurate count but can be resource-intensive for larger tables and views.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT COUNT(*) AS row_count
FROM database.schema.table;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Important note: Replace database, schema, and table with the appropriate identifiers for your Snowflake environment.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: Snowflake Metadata Queries
&lt;/h2&gt;

&lt;p&gt;Snowflake metadata views contain information about databases, schemas, tables, and views, but the row counts for views are not stored in these metadata. By querying the appropriate metadata view and filtering on the desired table, we can efficiently obtain row counts of tables, but this method is not applicable to views.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
  TABLE_CATALOG AS database,
  TABLE_SCHEMA AS schema,
  TABLE_NAME AS table,
  ROW_COUNT AS row_count
FROM 
  SNOWFLAKE.ACCOUNT_USAGE.TABLES
WHERE 
  TABLE_NAME = 'table'
  AND TABLE_SCHEMA = 'schema'
  AND TABLE_CATALOG = 'database';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Important note: Replace database, schema, and table with the correct identifiers for your Snowflake environment. Additionally, ensure your user has the necessary privileges to access the metadata views.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 3: Using Snowflake Information Schema
&lt;/h2&gt;

&lt;p&gt;Similar to metadata views, Snowflake provides an INFORMATION_SCHEMA containing metadata about databases, schemas, tables, and views. However, like the Snowflake metadata views, the row counts for views are not stored here, so this method is also not applicable to views. By querying the appropriate INFORMATION_SCHEMA view and filtering on the desired table, we can effectively obtain row counts of tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
  TABLE_CATALOG AS database,
  TABLE_SCHEMA AS schema,
  TABLE_NAME AS table,
  ROW_COUNT AS row_count
FROM 
  INFORMATION_SCHEMA.TABLES
WHERE 
  TABLE_NAME = 'table'
  AND TABLE_SCHEMA = 'schema'
  AND TABLE_CATALOG = 'database';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Important note: Replace database, schema, and table with the correct identifiers for your Snowflake environment. Ensure your user has the necessary privileges to access the INFORMATION_SCHEMA.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Obtaining row counts in Snowflake tables or views is crucial for various use cases. While the COUNT(*) method provides an accurate count, it can be resource-intensive for large tables. Alternatively, leveraging Snowflake metadata queries or INFORMATION_SCHEMA enables efficient row count retrieval. &lt;/p&gt;

&lt;p&gt;However, it's essential to note the necessary privileges required to access metadata views or INFORMATION_SCHEMA. Additionally, table statistics provide approximate row counts and may not always reflect the latest count. Choose the method that best suits your requirements based on table size, desired accuracy, and associated costs in your Snowflake environment.&lt;/p&gt;

</description>
      <category>rowcounts</category>
      <category>snowflake</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>3 ways to improve data sampling efficiency in Snowflake</title>
      <dc:creator>Metaplane</dc:creator>
      <pubDate>Fri, 01 Mar 2024 19:48:45 +0000</pubDate>
      <link>https://dev.to/metaplane/3-ways-to-improve-data-sampling-efficiency-in-snowflake-203a</link>
      <guid>https://dev.to/metaplane/3-ways-to-improve-data-sampling-efficiency-in-snowflake-203a</guid>
      <description>&lt;p&gt;The longer a query takes to execute, the more expensive it becomes. Not just in terms of compute resources, but also our most precious resource—time.&lt;/p&gt;

&lt;p&gt;While it’s not much of a problem when your tables are small, as your tables grow in size, the cost, execution, and iteration time of downstream tasks follow suit. That’s why writing efficient queries is just as important as writing queries that work.&lt;/p&gt;

&lt;p&gt;That's where conditional statements come into play. In Snowflake in particular, conditional statements can drastically reduce the resources and time spent on data queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do conditional statements in Snowflake make sampling queries more efficient?
&lt;/h2&gt;

&lt;p&gt;Think of conditional statements as setting up smart filters for your data collection. These “filters” sort through all the data and pick out just the bits that are actually useful and relevant to the problem you’re trying to solve. Like if you're fishing and you only want to catch salmon, you'd ideally use a net that only lets salmon through and keeps all the other fish out (if such a thing existed).&lt;/p&gt;

&lt;p&gt;Using conditional statements before you start sampling makes sure you’re only working with the data that matters, so you’re not wasting time and resources on data you don't need. And when you do take a representative sample, it's more likely to give you the information you need without hitting random data roadblocks (or worse, sampling bias/sampling error).&lt;/p&gt;

&lt;p&gt;With that said, we’re starting with a fairly simple sampling technique. It’s not a conditional statement per se, but it’s a great way to wrangle your larger datasets more efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: Using Partitioned Tables with Sampling
&lt;/h2&gt;

&lt;p&gt;Though more of a technique than a conditional statement, partitioning and sampling data in Snowflake is a great, easy way to enhance your query performance—especially if you’re using large datasets. Partitioning organizes the data based on certain keys or criteria, facilitating quicker access to relevant data segments and reducing the scope of data scans during queries. Essentially, it speeds up query execution by focusing only on pertinent data partitions.&lt;/p&gt;

&lt;p&gt;Sampling after partitioning allows you to work with a smaller sample size that represents the larger whole. By analyzing a sample, you can infer patterns, trends, and insights without the overhead of processing the entire dataset, saving you on data storage down the road.&lt;/p&gt;

&lt;p&gt;To combine these steps into a single SQL query in Snowflake, you’d typically make sure your table is organized into partitions based on a key that is relevant to your query patterns. But since Snowflake automatically manages micro-partitions and doesn’t allow manual partitioning like traditional databases, we'll focus on using cluster sampling for organizing and then sampling data.&lt;/p&gt;

&lt;p&gt;Here’s what that looks like in practice:&lt;/p&gt;

&lt;p&gt;Let's say we have a sales data table (sales_data), and we're interested in analyzing sales performance by region. We assume that the table is clustered by region_id to optimize performance for queries filtered by region. Now, we want to sample a subset of this data for a quick analysis using the SQL query below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT 
  * 
FROM 
  sales_data TABLESAMPLE BERNOULLI (10);
-- Sample approximately 10% of the rows
WHERE 
  region_id = 'NorthAmerica' -- Assuming you're interested in North American sales data
  AND DATE(sale_date) BETWEEN '2023-01-01' 
  AND '2023-12-31'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;‍&lt;br&gt;
In this case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WHERE region_id = 'NorthAmerica' focuses the query on the North American sales data, using the table's clustering on region_id to improve performance.&lt;/li&gt;
&lt;li&gt;AND DATE(sale_date) BETWEEN '2023-01-01' AND '2023-12-31' further filters the data to only include sales from the year 2023.&lt;/li&gt;
&lt;li&gt;TABLESAMPLE BERNOULLI (10) applies a sampling method to retrieve approximately 10% of the rows from the filtered result set. The BERNOULLI sampling method provides a random sample of the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This query is designed to efficiently filter and sample the data based on the table's organization (clustering by region_id)—it aligns the data with query patterns, and then samples the targeted subset of data.&lt;/p&gt;

&lt;p&gt;While partitioning is great for speeding up searches targeting specific regions, if your data isn't neatly organized around the criteria you're using to partition it, or if your searches don't align well with how the data is split up, partitioning won't help much. For instance, if you need information that's spread across multiple partitions, or if your search conditions change a lot and don't match the partitioning scheme, you might not see the performance boost you were hoping for. If that’s the case, you might want to investigate conditional statements.&lt;/p&gt;
&lt;h2&gt;
  
  
  Option 2: Using CASE statements
&lt;/h2&gt;

&lt;p&gt;Using CASE statements in your data sampling queries in Snowflake adds a layer of conditional logic to the sampling process, which is particularly useful when you want to apply different sampling rates or methods based on specific criteria within your data. &lt;/p&gt;

&lt;p&gt;For instance, you might want to sample more heavily in areas where your data is denser or more variable, and less so in more uniform areas. The CASE statement allows you to dynamically adjust the sampling rate or method based on the characteristics of the data (e.g. region, time period, or any other relevant dimension). &lt;/p&gt;

&lt;p&gt;To use CASE statements to analyze sales performance by region (like in the above sales_data table example), you can design a query that selects a sample of sales data based on certain conditions related to regions. Since Snowflake's SQL does not support using TABLESAMPLE directly within a CASE statement, you’ll have to use a workaround that involves filtering data in subqueries or using conditional logic to assign sample rates and then applying these rates in a subsequent operation.&lt;/p&gt;

&lt;p&gt;Here's what this looks like in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WITH region_sample AS (
  SELECT 
    sale_id, 
    region, 
    sale_amount, 
    CASE 
      WHEN sale_amount &amp;lt; 1000 THEN 1 
      WHEN sale_amount BETWEEN 1000 AND 10000 THEN 2 
      WHEN sale_amount &amp;gt; 10000 THEN 3 
    END AS sale_group 
  FROM 
    sales_data
), 
sampled_data AS (
  SELECT 
    * 
  FROM 
    region_sample 
  WHERE 
    (
      sale_group = 1 
      AND RANDOM() &amp;lt; 0.05
    ) -- For sales under $1000, sample ~5%
    OR (
      sale_group = 2 
      AND RANDOM() &amp;lt; 0.1
    ) -- For sales between $1000 and $10000, sample ~10%
    OR (
      sale_group = 3 
      AND RANDOM() &amp;lt; 0.15
    ) -- For sales over $10000, sample ~15%
) 
SELECT 
  * 
FROM 
  sampled_data;
‍
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The function above for ‘region_sample’ assigns a sample_group value to each row based on the region and sale_amount. Each region (and condition within the region) is associated with a different group.&lt;/li&gt;
&lt;li&gt;sampled_data then filters the region_sample data by applying a random sampling condition to each sample_group. The RANDOM() function generates a random value between 0 and 1, and rows are selected based on whether this random value falls below the specified threshold (e.g., 0.05 for a 5% sample rate).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than partitioning, this approach allows for nuanced sampling based on region and sales amount. As a result, you get a much more targeted data analysis of sales performance. &lt;/p&gt;

&lt;p&gt;But you also have to deal with increased complexity and reduced readability of your SQL queries. As you add more conditions and logic with CASE statements, the queries become harder to understand and maintain (which is especially true for teams where multiple analysts work on the same codebase). If this doesn’t work for your scenario, try using a JOIN. &lt;/p&gt;

&lt;h2&gt;
  
  
  Option 3: Using JOINS
&lt;/h2&gt;

&lt;p&gt;Using JOIN statements with conditional logic allows you to sample data based on relationships between tables or within subsets of a single table. You can create a derived table or a Common Table Expression (CTE) that contains the specific conditions or subsets you care about, then join this derived table or CTE with the original (or another related) table and apply the sampling on this joined result set.&lt;/p&gt;

&lt;p&gt;This method is particularly useful when the sampling criteria involve complex conditions or multiple tables.&lt;/p&gt;

&lt;p&gt;Now, back to the sales_data table example from above. Let's assume we have a related table (e.g.regions), that contains detailed information about different sales regions. And suppose we want to sample sales data from the NorthAmerica region more efficiently by joining the sales_data table with the regions table, which contains detailed region information.&lt;/p&gt;

&lt;p&gt;This is what that SQL query looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WITH RegionSales AS (
  SELECT 
    sd.* 
  FROM 
    sales_data sd 
    JOIN regions r ON sd.region_id = r.region_id 
  WHERE 
    r.region_name = 'NorthAmerica' -- Condition to filter sales data by region
    AND DATE(sd.sale_date) BETWEEN '2023-01-01' 
    AND '2023-12-31'
) 
SELECT 
  * 
FROM 
  RegionSales TABLESAMPLE BERNOULLI (10);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RegionSales creates a temporary result set that joins the sales_data table with the regions table. It filters the sales data to include only those records from the NorthAmerica region and within the specified date range ('2023-01-01' to '2023-12-31').&lt;/li&gt;
&lt;li&gt;The TABLESAMPLE BERNOULLI (10) clause is applied to this filtered and joined dataset, sampling approximately 10% of the rows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JOINS are particularly advantageous when the sampling criteria involves complex conditions or multiple tables that are interconnected. Imagine trying to get a snapshot of data that's spread across different tables, each with its own set of rules or relationships. JOINS bring all that related information together first, so you can then apply your sampling logic to one, combined dataset. This is super helpful when your analysis depends on understanding how different pieces of data relate to each other, like how customer profiles link to their purchase histories. &lt;/p&gt;

&lt;p&gt;But keep in mind: while JOINS are powerful for relating datasets, they’re not always the best choice if simplicity and performance are priorities. When you join tables, especially multiple or large ones, you increase the amount of data being processed before sampling can even occur which requires more compute resources upfront and slows down query execution time. Doing the JOIN after sampling will improve this efficiency slightly, but it won’t fix the problem entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better way
&lt;/h2&gt;

&lt;p&gt;Metaplane makes it easy for users to configure how they want their data to be sampled in future Snowflake queries. This includes options for users such as Time Windows and WHERE clauses. With Time Windows and “Include Data Since” options, users can configure their lookback periods to only include their most recent data. In WHERE clauses, users can further restrict the amount of data within a table being queried by any dimension of their table.&lt;/p&gt;

&lt;p&gt;As a bonus, consider using timestamp functions supported by your warehouse such as CURRENT_DATE() to scan data created or updated from today onwards, if your goal is to ensure that new data is accurate.&lt;/p&gt;

&lt;p&gt;Want to see how Metaplane’s configurable monitors can make your Snowflake data sampling more efficient? &lt;a href="https://www.metaplane.dev/book-a-demo"&gt;Talk to us&lt;/a&gt; or &lt;a href="https://metaplane.dev/signup"&gt;start a free trial today&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>tutorial</category>
      <category>learning</category>
      <category>snowflake</category>
    </item>
  </channel>
</rss>
