{"id":6984,"date":"2023-05-12T00:00:00","date_gmt":"2023-05-12T04:00:00","guid":{"rendered":"https:\/\/www.sisense.com\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/"},"modified":"2024-10-01T10:56:09","modified_gmt":"2024-10-01T14:56:09","slug":"hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql","status":"publish","type":"post","link":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/","title":{"rendered":"Hashing tables to ensure consistency in Postgres, Redshift and MySQL"},"content":{"rendered":"\r\n<h2 class=\"wp-block-heading\">Maintaining cache consistency<\/h2>\r\n\r\n\r\n\r\n<p>Maintaining a data cache optimized to serve different queries can help speed them up, and benefits from economies of scale.<\/p>\r\n\r\n\r\n\r\n<p>Maintaining this cache leads us to a critical question: How do I know if the cache is still valid? Put another way: <strong>How do I know if the data in a table in database A matches the data in a table in database B?<\/strong><\/p>\r\n\r\n\r\n\r\n<p>Enter <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hash_function\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">hashing<\/a>, a general technique to detect if two datasets are the same. We can use a hash to validate that our cache is fresh without needing to understand any application-specific logic.<\/p>\r\n\r\n\r\n\r\n<p>What we need now is a query that returns the exact same hash given the same table structure and data on all databases.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">The algorithm<\/h2>\r\n\r\n\r\n\r\n<p>For each row:<\/p>\r\n\r\n\r\n\r\n<ol class=\"wp-block-list\">\r\n<li>Take the MD5 of each column. Use a space for NULL values.<\/li>\r\n<li>Concatenate those results, and MD5 this result.<\/li>\r\n<li>Split into 4 8-character hex strings.<\/li>\r\n<li>Convert into 32-bit integers and sum.<\/li>\r\n<\/ol>\r\n\r\n\r\n\r\n<p>We choose MD5 as our hash function because it\u2019s fast and supported on all databases.<\/p>\r\n\r\n\r\n\r\n<p>We break the column hashes into integer-sized chunks and sum them to get a single value (4 bigints) in order to save memory and transfer time. Ideally we\u2019d hash all the individual column hashes, but this isn\u2019t possible on all databases.<\/p>\r\n\r\n\r\n\r\n<p>Finally, note that we must convert the columns into the same format before encoding in step (1) to ensure cross-database consistency.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">In Postgres<\/h2>\r\n\r\n\r\n\r\n<p>Taking the MD5 of a column looks like this:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>md5(\"column name\"::text)<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Some extra massaging may be required for more complex types. Examples of integers, text columns, and datetime columns are below.<\/p>\r\n\r\n\r\n\r\n<p>Now we\u2019ll layer on spaces for NULL values:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>coalesce(md5(\"column name\"::text), ' ')<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Concatenating and hashing those results is a simple matter:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>select md5(\r\n  coalesce(md5(\"column name\"::text), ' ') || \r\n  coalesce(md5(\"second column name\"::text), ' ')\r\n) as \"hash\"\r\nfrom \"my_table\".\"my_schema\"<\/code><\/pre>\r\n\r\n\r\n\r\n<p>We then wrap this all in a subquery so we can split the result into 4 8-character hex strings, which are each converted into 32-bit integers and summed.<\/p>\r\n\r\n\r\n\r\n<p>As we add that in, we get the final query:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>select\r\n  sum(('x' || substring(hash, 1, 8))::bit(32)::bigint),\r\n  sum(('x' || substring(hash, 9, 8))::bit(32)::bigint),\r\n  sum(('x' || substring(hash, 17, 8))::bit(32)::bigint),\r\n  sum(('x' || substring(hash, 25, 8))::bit(32)::bigint)\r\nfrom (\r\n  select md5 (\r\n    coalesce(md5(\"integer column\"::text), ' ') ||\r\n    coalesce(md5(floor(\r\n      extract(epoch from \"datetime column\")\r\n    )::text), ' ') ||\r\n    coalesce(md5(\"string column\"::text), ' ') ||\r\n    coalesce(md5(\"boolean column\"::integer::text), ' ')\r\n  ) as \"hash\"\r\n  from \"my_schema\".\"my_table\";\r\n) as t;<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Note the \u2018x\u2019 prepended to the hash strings, which tells Postgres to interpret them as hex strings when casting to a number.<\/p>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">In Redshift<\/h2>\r\n\r\n\r\n\r\n<p>Redshift supports the handy strtol function, making our hash-string-to-integer conversion a bit easier. Otherwise, the full query is the same:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>select\r\n  sum(trunc(strtol(substring(hash, 1, 8), 16))),\r\n  sum(trunc(strtol(substring(hash, 9, 8), 16))),\r\n  sum(trunc(strtol(substring(hash, 17, 8), 16))),\r\n  sum(trunc(strtol(substring(hash, 25, 8), 16)))\r\nfrom (\r\n  select md5(\r\n    coalesce(md5(\"integer column\"::text), ' ') ||\r\n    coalesce(md5(floor(\r\n      extract(epoch from \"datetime column\")\r\n    )::text), ' ') ||\r\n    coalesce(md5(\"string column\"::text), ' ') ||\r\n    coalesce(md5(\"boolean column\"::integer::text), ' ')\r\n  ) as \"hash\"\r\n  from \"my_schema\".\"my_table\"\r\n) as t;<\/code><\/pre>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">In MySQL<\/h2>\r\n\r\n\r\n\r\n<p>MySQL sports a few changes from the Postgres and Redshift variants:<\/p>\r\n\r\n\r\n\r\n<p>First, the syntax for casting many of the columns to helpful strings is different, e.g. for datetimes:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>floor(unixtimestamp(\"datetime column\"))<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Second, an explicit concat call is required to concatenate the column hashes, since we\u2019re missing Postgres\u2019s || syntax.<\/p>\r\n\r\n\r\n\r\n<p>Finally, we use conv to get our 32-bit numbers, and cast to cast them to integers:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>cast(conv(substring(hash, 1, 8), 16, 10) as unsigned)<\/code><\/pre>\r\n\r\n\r\n\r\n<p>Putting it all together, we get this final query:<\/p>\r\n\r\n\r\n\r\n<pre class=\"wp-block-code\"><code>select \r\n  sum(cast(conv(substring(hash, 1, 8), 16, 10) as unsigned)), \r\n  sum(cast(conv(substring(hash, 9, 8), 16, 10) as unsigned)), \r\n  sum(cast(conv(substring(hash, 17, 8), 16, 10) as unsigned)), \r\n  sum(cast(conv(substring(hash, 25, 8), 16, 10) as unsigned)) \r\nfrom (\r\n  select md5(\r\n    concat(\r\n      coalesce(md5(\"integer column\"), ' '),\r\n      coalesce(md5(floor(\r\n        unix_timestamp(\"datetime column\")\r\n      )), ' '), \r\n      coalesce(md5(\"string column\"), ' '), \r\n      coalesce(md5(cast(\"boolean column\" as integer)), ' ')\r\n    )\r\n  ) as \"hash\"\r\n  from \"my_table\"\r\n) as t;<\/code><\/pre>\r\n\r\n\r\n\r\n<h2 class=\"wp-block-heading\">In practice<\/h2>\r\n\r\n\r\n\r\n<p>The end result will be four bigints representing the state of the table. Changing any row will change the results.<\/p>\r\n\r\n\r\n\r\n<p>All this being said, we can\u2019t recommend that you write this all by hand! We\u2019ve open-sourced a <a href=\"https:\/\/gist.github.com\/compnski\/a89a5e53eb308671bd6e\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">simple Go script<\/a> to build the hash query given a database type and a list of columns names and types.<\/p>\r\n","protected":false},"excerpt":{"rendered":"<p>Maintaining cache consistency Maintaining a data cache optimized to serve different queries can help speed them up, and benefits from economies of scale. Maintaining this cache leads us to a critical question: How do I know if the cache is&#8230;<\/p>\n","protected":false},"author":4,"featured_media":7186,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_searchwp_excluded":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[44],"tags":[472],"application":[10],"buyer-role":[],"buyer-stage":[],"department":[],"industry":[],"topic":[],"class_list":["post-6984","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech-talk","tag-data-team","application-cloud-data-teams"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.5 (Yoast SEO v23.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Hashing Tables Consistency in Postgres, Redshift and MySQL<\/title>\n<meta name=\"description\" content=\"We can use a hash to validate that our cache is fresh, without needing to understand any application-specific logic.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Hashing tables to ensure consistency in Postgres, Redshift and MySQL\" \/>\n<meta property=\"og:description\" content=\"Maintaining cache consistency Maintaining a data cache optimized to serve different queries can help speed them up, and benefits from economies of scale.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/\" \/>\n<meta property=\"og:site_name\" content=\"Sisense\" \/>\n<meta property=\"article:published_time\" content=\"2023-05-12T04:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-10-01T14:56:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/yoast-hashing-blog-min.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Sisense Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/yoast-hashing-blog-min.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@sisense\" \/>\n<meta name=\"twitter:site\" content=\"@sisense\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sisense Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/\"},\"author\":{\"name\":\"Sisense Team\",\"@id\":\"https:\/\/www.sisense.com\/#\/schema\/person\/e70aa3a7bbc471e4b7b8c5a7d2b36115\"},\"headline\":\"Hashing tables to ensure consistency in Postgres, Redshift and MySQL\",\"datePublished\":\"2023-05-12T04:00:00+00:00\",\"dateModified\":\"2024-10-01T14:56:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/\"},\"wordCount\":511,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.sisense.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg\",\"keywords\":[\"data team\"],\"articleSection\":[\"Tech Talk\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/\",\"url\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/\",\"name\":\"Hashing Tables Consistency in Postgres, Redshift and MySQL\",\"isPartOf\":{\"@id\":\"https:\/\/www.sisense.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg\",\"datePublished\":\"2023-05-12T04:00:00+00:00\",\"dateModified\":\"2024-10-01T14:56:09+00:00\",\"description\":\"We can use a hash to validate that our cache is fresh, without needing to understand any application-specific logic.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage\",\"url\":\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg\",\"contentUrl\":\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg\",\"width\":1200,\"height\":628,\"caption\":\"featured hashing blog min\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sisense.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Hashing tables to ensure consistency in Postgres, Redshift and MySQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sisense.com\/#website\",\"url\":\"https:\/\/www.sisense.com\/\",\"name\":\"Sisense\",\"description\":\"Build your business with anywhere-analytics\",\"publisher\":{\"@id\":\"https:\/\/www.sisense.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sisense.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.sisense.com\/#organization\",\"name\":\"Sisense\",\"url\":\"https:\/\/www.sisense.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sisense.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/sisense-yoast-og.jpg\",\"contentUrl\":\"https:\/\/cdn.sisense.com\/wp-content\/uploads\/sisense-yoast-og.jpg\",\"width\":1200,\"height\":600,\"caption\":\"Sisense\"},\"image\":{\"@id\":\"https:\/\/www.sisense.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/sisense\",\"https:\/\/www.linkedin.com\/company\/sisense\",\"https:\/\/github.com\/sisense\/\"],\"description\":\"Sisense accelerates product innovation through AI\/ML capabilities. Our global analytics platform lets customers drive better, faster decisions for their business and end users.\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sisense.com\/#\/schema\/person\/e70aa3a7bbc471e4b7b8c5a7d2b36115\",\"name\":\"Sisense Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sisense.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/213e415f47bc3c7f0155a0755b1cea8c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/213e415f47bc3c7f0155a0755b1cea8c?s=96&d=mm&r=g\",\"caption\":\"Sisense Team\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Hashing Tables Consistency in Postgres, Redshift and MySQL","description":"We can use a hash to validate that our cache is fresh, without needing to understand any application-specific logic.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/","og_locale":"en_US","og_type":"article","og_title":"Hashing tables to ensure consistency in Postgres, Redshift and MySQL","og_description":"Maintaining cache consistency Maintaining a data cache optimized to serve different queries can help speed them up, and benefits from economies of scale.","og_url":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/","og_site_name":"Sisense","article_published_time":"2023-05-12T04:00:00+00:00","article_modified_time":"2024-10-01T14:56:09+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/yoast-hashing-blog-min.jpg","type":"image\/jpeg"}],"author":"Sisense Team","twitter_card":"summary_large_image","twitter_image":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/yoast-hashing-blog-min.jpg","twitter_creator":"@sisense","twitter_site":"@sisense","twitter_misc":{"Written by":"Sisense Team","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#article","isPartOf":{"@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/"},"author":{"name":"Sisense Team","@id":"https:\/\/www.sisense.com\/#\/schema\/person\/e70aa3a7bbc471e4b7b8c5a7d2b36115"},"headline":"Hashing tables to ensure consistency in Postgres, Redshift and MySQL","datePublished":"2023-05-12T04:00:00+00:00","dateModified":"2024-10-01T14:56:09+00:00","mainEntityOfPage":{"@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/"},"wordCount":511,"commentCount":0,"publisher":{"@id":"https:\/\/www.sisense.com\/#organization"},"image":{"@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage"},"thumbnailUrl":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg","keywords":["data team"],"articleSection":["Tech Talk"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/","url":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/","name":"Hashing Tables Consistency in Postgres, Redshift and MySQL","isPartOf":{"@id":"https:\/\/www.sisense.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage"},"image":{"@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage"},"thumbnailUrl":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg","datePublished":"2023-05-12T04:00:00+00:00","dateModified":"2024-10-01T14:56:09+00:00","description":"We can use a hash to validate that our cache is fresh, without needing to understand any application-specific logic.","breadcrumb":{"@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#primaryimage","url":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg","contentUrl":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/2014\/06\/10161603\/featured-hashing-blog-min.jpg","width":1200,"height":628,"caption":"featured hashing blog min"},{"@type":"BreadcrumbList","@id":"https:\/\/www.sisense.com\/blog\/hashing-tables-to-ensure-consistency-in-postgres-redshift-and-mysql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sisense.com\/"},{"@type":"ListItem","position":2,"name":"Hashing tables to ensure consistency in Postgres, Redshift and MySQL"}]},{"@type":"WebSite","@id":"https:\/\/www.sisense.com\/#website","url":"https:\/\/www.sisense.com\/","name":"Sisense","description":"Build your business with anywhere-analytics","publisher":{"@id":"https:\/\/www.sisense.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sisense.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.sisense.com\/#organization","name":"Sisense","url":"https:\/\/www.sisense.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sisense.com\/#\/schema\/logo\/image\/","url":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/sisense-yoast-og.jpg","contentUrl":"https:\/\/cdn.sisense.com\/wp-content\/uploads\/sisense-yoast-og.jpg","width":1200,"height":600,"caption":"Sisense"},"image":{"@id":"https:\/\/www.sisense.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/sisense","https:\/\/www.linkedin.com\/company\/sisense","https:\/\/github.com\/sisense\/"],"description":"Sisense accelerates product innovation through AI\/ML capabilities. Our global analytics platform lets customers drive better, faster decisions for their business and end users."},{"@type":"Person","@id":"https:\/\/www.sisense.com\/#\/schema\/person\/e70aa3a7bbc471e4b7b8c5a7d2b36115","name":"Sisense Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sisense.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/213e415f47bc3c7f0155a0755b1cea8c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/213e415f47bc3c7f0155a0755b1cea8c?s=96&d=mm&r=g","caption":"Sisense Team"}}]}},"_links":{"self":[{"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/posts\/6984"}],"collection":[{"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/comments?post=6984"}],"version-history":[{"count":0,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/posts\/6984\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/media\/7186"}],"wp:attachment":[{"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/media?parent=6984"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/categories?post=6984"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/tags?post=6984"},{"taxonomy":"application","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/application?post=6984"},{"taxonomy":"buyer-role","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/buyer-role?post=6984"},{"taxonomy":"buyer-stage","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/buyer-stage?post=6984"},{"taxonomy":"department","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/department?post=6984"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/industry?post=6984"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.sisense.com\/wp-json\/wp\/v2\/topic?post=6984"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}