{"id":7785,"date":"2016-05-03T19:11:08","date_gmt":"2016-05-03T17:11:08","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/"},"modified":"2016-05-03T19:11:08","modified_gmt":"2016-05-03T17:11:08","slug":"when-a-query-has-read-350tb-after-73k-nested-loops","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/","title":{"rendered":"When a query has read 350TB after 73K nested loops"},"content":{"rendered":"<h2>By Franck Pachot<\/h2>\n<p>.<br \/>\nAccording that you have Tuning Pack, SQL Monitor is the right way to see what a query is currently doing. A query was running for days and the first figure I see is that it has read 350TB. This is not the kind of thing you do in only one operation, so I immediately checked the &#8216;executions&#8217; columns: 73K table scans. So that&#8217;s finally only 5GB. The problem is not the full scan, but the nested loop that iterates into it.<br \/>\n<!--more--><br \/>\nHere&#8217;s the tweet that reclaim some more explanation:<\/p>\n<blockquote class=\"twitter-tweet\" data-width=\"500\" data-dnt=\"true\">\n<p lang=\"en\" dir=\"ltr\">LOL. A case where Adaptive Plan would have been a good idea&#8230; time to switch to hash join after reading 350TB \ud83d\ude09 <a href=\"https:\/\/t.co\/iLEszMdpZQ\">pic.twitter.com\/iLEszMdpZQ<\/a><\/p>\n<p>&mdash; Franck Pachot (@FranckPachot) <a href=\"https:\/\/twitter.com\/FranckPachot\/status\/727051462363222016?ref_src=twsrc%5Etfw\">May 2, 2016<\/a><\/p><\/blockquote>\n<p><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><br \/>\nFinally it could have been worse. The nested loop has iterated 21M times and thanks to the filter we did only 73K full table scans.<\/p>\n<p>The problem is not the full table scan. 21M access by index would not have been better. The problem is nested loop. You can expect a hash join for that. I tried to force a hash join in vain and finally checked the query. I&#8217;ve reproduced it with same idea on a small table.<\/p>\n<p>Here are the table creation:<\/p>\n<pre><code>\ncreate table demo as select rownum id from xmltable('1 to 10');\ncreate table repart (rep_id number, id1 number, id2 number , x char);\ninsert into repart select rownum*4+0 ,   id id1, null id2 , 'A' from demo where id between 1 and 3;\ninsert into repart select rownum*4+1 , null id1,   id id2 , 'B' from demo where id between 3 and 5;\ninsert into repart select rownum*4+2 , null id1, null id2 , 'C' from demo where id between 5 and 7;\ninsert into repart select rownum*4+3 ,   id id1,   id id2 , 'D' from demo where id between 7 and 9;\n<\/code><\/pre>\n<p>table DEMO has rows with id from 1 to 10 and table REPART have rows that may match this 1 to 10 number wither in ID1 or in ID2<\/p>\n<pre><code>\nSQL&gt; select * from repart;\n&nbsp;\n    REP_ID        ID1        ID2 X\n---------- ---------- ---------- -\n         4          1            A\n         8          2            A\n        12          3            A\n         5                     3 B\n         9                     4 B\n        13                     5 B\n         6                       C\n        10                       C\n        14                       C\n         7          7          7 D\n        11          8          8 D\n        15          9          9 D\n&nbsp;\n12 rows selected.\n<\/code><\/pre>\n<p>And the user wants to get the rows that match one of them. He wants all rows from DEMO, then the value of &#8220;X&#8221; in REPART that matches with ID1 and if no row matches ID1 but matches ID2, he wants the &#8220;X&#8221; from this row. Not too hard to write: left outer joins, and a coalesce to get the first not null:<\/p>\n<pre><code>\nSQL&gt; select id,coalesce(repart1.x,repart2.x) from demo\n    left outer join repart repart1 on demo.id=repart1.id1\n    left outer join repart repart2 on demo.id=repart2.id2\n    where repart1.rep_id is not null or repart2.rep_id is not null\n    \/\n&nbsp;\n        ID C\n---------- -\n         3 A\n         4 B\n         5 B\n         7 D\n         8 D\n         9 D\n         1 A\n         2 A\n<\/code><\/pre>\n<p>And the plan is ok with hash join:<\/p>\n<pre><code>\nPlan hash value: 3945081217\n&nbsp;\n--------------------------------------------------------------------------------------------------------------------\n| Id  | Operation            | Name   | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |\n--------------------------------------------------------------------------------------------------------------------\n|   0 | SELECT STATEMENT     |        |      1 |        |      8 |00:00:00.01 |      18 |       |       |          |\n|*  1 |  FILTER              |        |      1 |        |      8 |00:00:00.01 |      18 |       |       |          |\n|*  2 |   HASH JOIN OUTER    |        |      1 |     10 |     10 |00:00:00.01 |      18 |  1888K|  1888K| 1131K (0)|\n|*  3 |    HASH JOIN OUTER   |        |      1 |     10 |     10 |00:00:00.01 |      10 |  2440K|  2440K| 1468K (0)|\n|   4 |     TABLE ACCESS FULL| DEMO   |      1 |     10 |     10 |00:00:00.01 |       3 |       |       |          |\n|   5 |     TABLE ACCESS FULL| REPART |      1 |     12 |     12 |00:00:00.01 |       7 |       |       |          |\n|   6 |    TABLE ACCESS FULL | REPART |      1 |     12 |     12 |00:00:00.01 |       8 |       |       |          |\n--------------------------------------------------------------------------------------------------------------------\n&nbsp;\nPredicate Information (identified by operation id):\n---------------------------------------------------\n&nbsp;\n   1 - filter((\"REPART1\".\"REP_ID\" IS NOT NULL OR \"REPART2\".\"REP_ID\" IS NOT NULL))\n   2 - access(\"DEMO\".\"ID\"=\"REPART2\".\"ID2\")\n   3 - access(\"DEMO\".\"ID\"=\"REPART1\".\"ID1\")\n<\/code><\/pre>\n<p>but this is not the query I&#8217;ve seen. Actually, the user tried to optimize it. He wants to read REPART for ID2 only when there were no match for ID1. So his idea was to add a predicate in the join so that we join to REPART.ID2 only when REPART.ID1 is null:<\/p>\n<pre><code>\nSQL&gt; select id,coalesce(repart1.x,repart2.x) from demo\n    left outer join repart repart1 on demo.id=repart1.id1\n    left outer join repart repart2 on demo.id=repart2.id2\n    \/* added *\/ and repart1.rep_id is null\n    where repart1.rep_id is not null or repart2.rep_id is not null\n    \/\n&nbsp;\n        ID C\n---------- -\n         1 A\n         2 A\n         3 A\n         7 D\n         8 D\n         9 D\n         5 B\n         4 B\n<\/code><\/pre>\n<p>This attempt to optimize is there in the FILTER operation. And this is why in the original query we had to access only 73K times instead of 21M. But in order to do that, the optimizer has implemented the outer join to a lateral view through a nested loop: <\/p>\n<pre><code>\nPlan hash value: 1922575045\n&nbsp;\n------------------------------------------------------------------------------------------------------------------------------\n| Id  | Operation             | Name            | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |\n------------------------------------------------------------------------------------------------------------------------------\n|   0 | SELECT STATEMENT      |                 |      1 |        |      8 |00:00:00.01 |      39 |       |       |          |\n|*  1 |  FILTER               |                 |      1 |        |      8 |00:00:00.01 |      39 |       |       |          |\n|   2 |   NESTED LOOPS OUTER  |                 |      1 |     10 |     10 |00:00:00.01 |      39 |       |       |          |\n|*  3 |    HASH JOIN OUTER    |                 |      1 |     10 |     10 |00:00:00.01 |      11 |  2440K|  2440K| 1414K (0)|\n|   4 |     TABLE ACCESS FULL | DEMO            |      1 |     10 |     10 |00:00:00.01 |       3 |       |       |          |\n|   5 |     TABLE ACCESS FULL | REPART          |      1 |     12 |     12 |00:00:00.01 |       8 |       |       |          |\n|   6 |    VIEW               | VW_LAT_3A0EC601 |     10 |      1 |      2 |00:00:00.01 |      28 |       |       |          |\n|*  7 |     FILTER            |                 |     10 |        |      2 |00:00:00.01 |      28 |       |       |          |\n|*  8 |      TABLE ACCESS FULL| REPART          |      4 |      1 |      2 |00:00:00.01 |      28 |       |       |          |\n------------------------------------------------------------------------------------------------------------------------------\n&nbsp;\nPredicate Information (identified by operation id):\n---------------------------------------------------\n&nbsp;\n   1 - filter((\"REPART1\".\"REP_ID\" IS NOT NULL OR \"ITEM_1\" IS NOT NULL))\n   3 - access(\"DEMO\".\"ID\"=\"REPART1\".\"ID1\")\n   7 - filter(\"REPART1\".\"REP_ID\" IS NULL)\n   8 - filter(\"DEMO\".\"ID\"=\"REPART2\".\"ID2\")\n<\/code><\/pre>\n<p>If I check how the query is transformed:<\/p>\n<pre><code>\nSQL&gt; exec dbms_sqldiag.dump_trace(p_sql_id=&gt;'4s003zk0ggftd',p_child_number=&gt;0,p_component=&gt;'Compiler',p_file_id=&gt;'TB350');\nPL\/SQL procedure successfully completed.\n<\/code><\/pre>\n<p>I can see that it has been transformed to a lateral view in order to include the predicate on the left table column:<\/p>\n<pre><code>\nFinal query after transformations:******* UNPARSED QUERY IS *******\nSELECT \"DEMO\".\"ID\" \"ID\",COALESCE(\"REPART1\".\"X\",\"VW_LAT_3A0EC601\".\"ITEM_4_3\") \"COALESCE(REPART1.X,REPART2.X)\" FROM \"DEMO\".\"DEMO\" \"DEMO\",\"DEMO\".\"REPART\" \"REPART1\", LATERAL( (SELECT \"REPART2\".\"REP_ID\" \"ITEM_1_0\",\"REPART2\".\"X\" \"ITEM_4_3\" FROM \"DEMO\".\"REPART\" \"REPART2\" WHERE \"DEMO\".\"ID\"=\"REPART2\".\"ID2\" AND \"REPART1\".\"REP_ID\" IS NULL))(+) \"VW_LAT_3A0EC601\" WHERE (\"REPART1\".\"REP_ID\" IS NOT NULL OR \"VW_LAT_3A0EC601\".\"ITEM_1_0\" IS NOT NULL) AND \"DEMO\".\"ID\"=\"REPART1\".\"ID1\"(+)\n<\/code><\/pre>\n<p>and this can be joined only with nested loop&#8230;<\/p>\n<p>Sometimes, it&#8217;s better to let the optimizer optimize rather than trying to do it ourselves because we can reduce the possibilities of join methods.<br \/>\nOf course, hash join had other problems such as the size of workarea. That&#8217;s what happens when we try to do some reporting on a table that has not been designed for it at all.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>By Franck Pachot . According that you have Tuning Pack, SQL Monitor is the right way to see what a query is currently doing. A query was running for days and the first figure I see is that it has read 350TB. This is not the kind of thing you do in only one operation, [&hellip;]<\/p>\n","protected":false},"author":27,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229],"tags":[829,96],"type_dbi":[],"class_list":["post-7785","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","tag-lateral","tag-oracle"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>When a query has read 350TB after 73K nested loops - dbi Blog<\/title>\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.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"When a query has read 350TB after 73K nested loops\" \/>\n<meta property=\"og:description\" content=\"By Franck Pachot . According that you have Tuning Pack, SQL Monitor is the right way to see what a query is currently doing. A query was running for days and the first figure I see is that it has read 350TB. This is not the kind of thing you do in only one operation, [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-05-03T17:11:08+00:00\" \/>\n<meta name=\"author\" content=\"Oracle Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Oracle Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/\"},\"author\":{\"name\":\"Oracle Team\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee\"},\"headline\":\"When a query has read 350TB after 73K nested loops\",\"datePublished\":\"2016-05-03T17:11:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/\"},\"wordCount\":495,\"commentCount\":0,\"keywords\":[\"lateral\",\"Oracle\"],\"articleSection\":[\"Database Administration &amp; Monitoring\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/\",\"name\":\"When a query has read 350TB after 73K nested loops - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2016-05-03T17:11:08+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"When a query has read 350TB after 73K nested loops\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee\",\"name\":\"Oracle Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g\",\"caption\":\"Oracle Team\"},\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/oracle-team\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"When a query has read 350TB after 73K nested loops - dbi Blog","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.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/","og_locale":"en_US","og_type":"article","og_title":"When a query has read 350TB after 73K nested loops","og_description":"By Franck Pachot . According that you have Tuning Pack, SQL Monitor is the right way to see what a query is currently doing. A query was running for days and the first figure I see is that it has read 350TB. This is not the kind of thing you do in only one operation, [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/","og_site_name":"dbi Blog","article_published_time":"2016-05-03T17:11:08+00:00","author":"Oracle Team","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Oracle Team","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/"},"author":{"name":"Oracle Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee"},"headline":"When a query has read 350TB after 73K nested loops","datePublished":"2016-05-03T17:11:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/"},"wordCount":495,"commentCount":0,"keywords":["lateral","Oracle"],"articleSection":["Database Administration &amp; Monitoring"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/","url":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/","name":"When a query has read 350TB after 73K nested loops - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2016-05-03T17:11:08+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/when-a-query-has-read-350tb-after-73k-nested-loops\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"When a query has read 350TB after 73K nested loops"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/66ab87129f2d357f09971bc7936a77ee","name":"Oracle Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f711f7cd2c9b09bf2627133755b569fb5be0694810cfd33033bdd095fedba86d?s=96&d=mm&r=g","caption":"Oracle Team"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/oracle-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/7785","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/27"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=7785"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/7785\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=7785"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=7785"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=7785"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=7785"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}