{"id":782,"date":"2018-05-29T21:05:03","date_gmt":"2018-05-29T19:05:03","guid":{"rendered":"http:\/\/blog.sqlora.com\/en\/?p=782"},"modified":"2018-11-04T20:00:15","modified_gmt":"2018-11-04T18:00:15","slug":"online-statistics-gathering-for-etl-part-2","status":"publish","type":"post","link":"https:\/\/blog.sqlora.com\/en\/online-statistics-gathering-for-etl-part-2\/","title":{"rendered":"Online Statistics Gathering for ETL &#8211; Part 2"},"content":{"rendered":"<p>In the <a href=\"https:\/\/blog.sqlora.com\/en\/online-statistics-gathering-for-etl-part-1\/\" rel=\"noopener\" target=\"_blank\">first part<\/a> we looked at general preconditions for online statistics gathering to work and some restrictions. In this part we&#8217;ll take a look at what happens with direct path loads into partitioned tables. <!--more--><\/p>\n<p><strong>Partitioning<\/strong><\/p>\n<p>There are also some points to consider while working with partitioned tables. First, inserting into an empty partitioned table will gather only <strong>global table statistics<\/strong>. Listing 1 shows that. Also as expected, if we then issue subsequent INSERT statement, which bulk inserts into another (yet empty) partition, nothing will happen. <\/p>\n<pre class=\"brush: sql; collapse: true; light: false; title: ; toolbar: true; notranslate\" title=\"\">\r\nSQL&gt; DROP table t_part purge;\r\n\r\nTable T_PART dropped.\r\n\r\nSQL&gt; CREATE TABLE t_part (pkey number, id number, s varchar2(20))\r\npartition by range (pkey)\r\n(partition P0 values less than (0),\r\npartition P1 values less than (1),\r\npartition P2 values less than (2),\r\npartition P3 values less than (3));\r\n\r\nTable T_PART created.\r\n\r\nSQL&gt; exec dbms_stats.set_table_prefs(null,'T_PART','INCREMENTAL','FALSE')\r\n\r\nPL\/SQL procedure successfully completed.\r\n\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part\r\nSELECT -1 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTI GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ----- ----- ------------------- ----------\r\nT_PART           NO    21-05-2018 05:10:46      10000\r\nT_PART     P0    NO                                  \r\nT_PART     P1    NO                                  \r\nT_PART     P3    NO                                  \r\nT_PART     P2    NO                                  \r\n\r\nSQL&gt; -- Now insert into another (empty) partition\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part\r\nSELECT 0 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; -- No statistics have been gathered this time\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTI GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ----- ----- ------------------- ----------\r\nT_PART           NO    21-05-2018 05:10:46      10000\r\nT_PART     P0    NO                                  \r\nT_PART     P1    NO                                  \r\nT_PART     P3    NO                                  \r\nT_PART     P2    NO                   \r\n<\/pre>\n<p><em><strong>Listing 1 &#8211; inserting into an empty partitioned table gathers only global stats<\/strong><\/em><\/p>\n<p>But you can use an extended syntax and explicitly provide the partition to insert into (Listing 2). What happens then? If this partition was empty, then <strong>partition level<\/strong> statistics will be gathered online. No global statistics that time:<\/p>\n<pre class=\"brush: sql; collapse: true; light: false; title: ; toolbar: true; notranslate\" title=\"\">\r\nSQL&gt; DROP table t_part purge;\r\n\r\nTable T_PART dropped.\r\n\r\nSQL&gt; CREATE TABLE t_part (pkey number, id number, s varchar2(20))\r\npartition by range (pkey)\r\n(partition P0 values less than (0),\r\npartition P1 values less than (1),\r\npartition P2 values less than (2),\r\npartition P3 values less than (3));\r\n\r\nTable T_PART created.\r\n\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part PARTITION (P2)\r\nSELECT 1 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTI GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ----- ----- ------------------- ----------\r\nT_PART           NO                                  \r\nT_PART     P1    NO                                  \r\nT_PART     P2    NO    21-05-2018 05:30:24      10000\r\nT_PART     P0    NO                                  \r\nT_PART     P3    NO                                  \r\n \r\n<\/pre>\n<p><em><strong>Listing 2 &#8211; partition level stats if explicitly specifying partition <\/strong><\/em><\/p>\n<p>Even better, if we change the preference for gathering global table statistics to incremental, the synopsis for the changed partition will be created altogether. The prerequisite is using the extended syntax explicitly specifying the partition.<\/p>\n<pre class=\"brush: sql; collapse: true; light: false; title: ; toolbar: true; notranslate\" title=\"\">\r\nSQL&gt; DROP table t_part purge;\r\n\r\nTable T_PART dropped.\r\n\r\nSQL&gt; CREATE TABLE t_part (pkey number, id number, s varchar2(20))\r\npartition by range (pkey)\r\n(partition P0 values less than (0),\r\npartition P1 values less than (1),\r\npartition P2 values less than (2),\r\npartition P3 values less than (3));\r\n\r\nTable T_PART created.\r\n\r\nSQL&gt; exec dbms_stats.set_table_prefs(null,'T_PART','INCREMENTAL','TRUE')\r\n\r\nPL\/SQL procedure successfully completed.\r\n\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part PARTITION (P3)\r\nSELECT 2 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTI GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ----- ----- ------------------- ----------\r\nT_PART           NO                                  \r\nT_PART     P0    NO                                  \r\nT_PART     P1    NO                                  \r\nT_PART     P2    NO                                  \r\nT_PART     P3    NO    21-05-2018 12:06:57      10000\r\n\r\nSQL&gt; -- Check Synopsis\r\nSQL&gt; SELECT o.name         Table_Name,\r\n       p.subname      Partition_name,\r\n       c.name         &quot;Column&quot;,\r\n       h.analyzetime  &quot;Synopsis Creation Time&quot;\r\nFROM   sys.WRI$_OPTSTAT_SYNOPSIS_HEAD$ h,\r\n       sys.OBJ$ o,\r\n       sys.COL$ c,\r\n       ( ( SELECT TABPART$.bo#  BO#,\r\n                  TABPART$.obj# OBJ#\r\n           FROM   sys.TABPART$ tabpart$ )\r\n         UNION ALL\r\n         ( SELECT TABCOMPART$.bo#  BO#,\r\n                  TABCOMPART$.obj# OBJ#\r\n           FROM   sys.TABCOMPART$ tabcompart$ ) ) tp,\r\n       sys.OBJ$ p\r\nWHERE  o.name = 'T_PART' AND\r\n       tp.obj# = p.obj# AND\r\n       h.bo# = tp.bo# AND\r\n       h.group# = tp.obj# * 2 AND\r\n       h.bo# = c.obj#(+) AND\r\n       h.intcol# = c.intcol#(+) AND\r\n       h.bo# = o.obj#\r\nORDER  BY 4,1,2,3;\r\n\r\nTABLE_NAME PARTI Colum Synopsis Creation Time\r\n---------- ----- ----- ----------------------\r\nT_PART     P3    ID    21-05-2018 12:06:57   \r\nT_PART     P3    PKEY  21-05-2018 12:06:57   \r\nT_PART     P3    S     21-05-2018 12:06:57   \r\n \r\n<\/pre>\n<p><em><strong>Listing 3 &#8211; partition level plus synopsis if explicitly specifying partition <\/strong><\/em><\/p>\n<p>But what happens if we don&#8217;t use the extended syntax leaving the incremental preference to be true? Nothing will happen, no online statistics at all!<\/p>\n<pre class=\"brush: sql; collapse: true; light: false; title: ; toolbar: true; notranslate\" title=\"\">\r\nSQL&gt; DROP table t_part purge;\r\n\r\nTable T_PART dropped.\r\n\r\nSQL&gt; CREATE TABLE t_part (pkey number, id number, s varchar2(20))\r\npartition by range (pkey)\r\n(partition P0 values less than (0),\r\npartition P1 values less than (1),\r\npartition P2 values less than (2),\r\npartition P3 values less than (3));\r\n\r\nTable T_PART created.\r\n\r\nSQL&gt; exec dbms_stats.set_table_prefs(null,'T_PART','INCREMENTAL','TRUE')\r\n\r\nPL\/SQL procedure successfully completed.\r\n\r\nSQL&gt; -- without partition-syntax\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part\r\nSELECT 0 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTI GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ----- ----- ------------------- ----------\r\nT_PART           NO                                  \r\nT_PART     P1    NO                                  \r\nT_PART     P2    NO                                  \r\nT_PART     P3    NO                                  \r\nT_PART     P0    NO                                  \r\n\r\nSQL&gt; -- Check Synopsis\r\nSQL&gt; SELECT o.name         Table_Name,\r\n       p.subname      Partition_name,\r\n       c.name         &quot;Column&quot;,\r\n       h.analyzetime  &quot;Synopsis Creation Time&quot;\r\nFROM   sys.WRI$_OPTSTAT_SYNOPSIS_HEAD$ h,\r\n       sys.OBJ$ o,\r\n       sys.COL$ c,\r\n       ( ( SELECT TABPART$.bo#  BO#,\r\n                  TABPART$.obj# OBJ#\r\n           FROM   sys.TABPART$ tabpart$ )\r\n         UNION ALL\r\n         ( SELECT TABCOMPART$.bo#  BO#,\r\n                  TABCOMPART$.obj# OBJ#\r\n           FROM   sys.TABCOMPART$ tabcompart$ ) ) tp,\r\n       sys.OBJ$ p\r\nWHERE  o.name = 'T_PART' AND\r\n       tp.obj# = p.obj# AND\r\n       h.bo# = tp.bo# AND\r\n       h.group# = tp.obj# * 2 AND\r\n       h.bo# = c.obj#(+) AND\r\n       h.intcol# = c.intcol#(+) AND\r\n       h.bo# = o.obj#\r\nORDER  BY 4,1,2,3;\r\n\r\nno rows selected\r\n \r\n<\/pre>\n<p><em><strong>Listing 4 &#8211; no stats with incremental = true and not explicitly specifying partition <\/strong><\/em><\/p>\n<p>We can show the different cases in the table:<\/p>\n\n<table id=\"tablepress-3\" class=\"tablepress tablepress-id-3\">\n<thead>\n<tr class=\"row-1\">\n\t<td class=\"column-1\"><\/td><th class=\"column-2\">Incremental Preference TRUE<\/th><th class=\"column-3\">Incremental Preference FALSE<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-striping row-hover\">\n<tr class=\"row-2\">\n\t<td class=\"column-1\">Partition name specified<\/td><td class=\"column-2\">partition-level stats + synopsis<\/td><td class=\"column-3\">partition-level stats<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">No partition name specified<\/td><td class=\"column-2\">No stats at all!<\/td><td class=\"column-3\">global stats<br \/>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<!-- #tablepress-3 from cache -->\n<p>Well, I have one more question, which I think can simply be a bug. If we don&#8217;t reference partitions explicitly and thus get only table-level statistics, why is the column GLOBAL_STATS in USER_TAB_STATISTICS  shown as NO? The meaning of NO is that table-level statistics have been aggregated from partition-level statistics and YES means they have been explicitly gathered or set. Well, in our case they are definitely not aggregated from partition-level but are gathered on the fly <\/p>\n<p><em><strong>Interval Partitioning<\/strong><\/em><\/p>\n<p>There are two reasons to explicitly mention interval partitioning. The first reason is that in 12.1 no online statistics gathering takes place with bulk INSERT in the case of interval partitioned tables. It is a known bug  (Doc ID 20562261.8) and it is fixed in 12.2. The second reason is the question that may arise with interval partitioning: how can we get partition-level statistics? Without specifying a partition we&#8217;ll get only global statistics. On the other hand, we don&#8217;t create empty partitions beforehand, instead they are automatically created by an INSERT.  But how can I specify a partition which doesn&#8217;t exist yet? Well, there is a way to do this: the extended partition syntax allows not only to specify the partition name, but also the value. The database automatically determines the right partition. This is shown in Listing 5. Interesting fact, if the table preference is to use incremental statistics, then a synopsis for affected partition is also created but we cannot see its creation time. <\/p>\n<pre class=\"brush: sql; collapse: true; light: false; title: ; toolbar: true; notranslate\" title=\"\">\r\nSQL&gt; DROP table t_part purge;\r\n\r\nTable T_PART dropped.\r\n\r\nSQL&gt; CREATE TABLE t_part (pkey number, id number, s varchar2(20))\r\npartition by range (pkey) interval (1)\r\n(partition P0 values less than (0)\r\n);\r\n\r\nTable T_PART created.\r\n\r\nSQL&gt; -- without partition-syntax\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part \r\nSELECT 0 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTITION_ GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ---------- ----- ------------------- ----------\r\nT_PART                NO    23-05-2018 03:45:10      10000\r\nT_PART     SYS_P961   NO                                  \r\nT_PART     P0         NO                                  \r\n\r\nSQL&gt; -- With partition for\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part partition for (1) tp\r\nSELECT 1 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTITION_ GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ---------- ----- ------------------- ----------\r\nT_PART                NO    23-05-2018 03:45:10      10000\r\nT_PART     SYS_P961   NO                                  \r\nT_PART     P0         NO                                  \r\nT_PART     SYS_P962   NO    23-05-2018 03:45:10      10000\r\n\r\nSQL&gt; -- With partition for + incremental\r\nSQL&gt; exec dbms_stats.set_table_prefs(null,'T_PART','INCREMENTAL','TRUE')\r\n\r\nPL\/SQL procedure successfully completed.\r\n\r\nSQL&gt; INSERT \/*+ append *\/ INTO   t_part partition for (2) tp\r\nSELECT 2 pkey, level AS id , lpad (level, 20, '0') s\r\nFROM   dual\r\nCONNECT BY level &lt;= 10000;\r\n\r\n10,000 rows inserted.\r\n\r\nSQL&gt; COMMIT;\r\n\r\nCommit complete.\r\n\r\nSQL&gt; SELECT table_name, partition_name, global_stats, last_analyzed, num_rows\r\nFROM   user_tab_statistics s\r\nWHERE  table_name IN ('T_PART');\r\n\r\nTABLE_NAME PARTITION_ GLOBA LAST_ANALYZED         NUM_ROWS\r\n---------- ---------- ----- ------------------- ----------\r\nT_PART                NO    23-05-2018 03:45:10      10000\r\nT_PART     SYS_P961   NO                                  \r\nT_PART     P0         NO                                  \r\nT_PART     SYS_P962   NO    23-05-2018 03:45:10      10000\r\nT_PART     SYS_P963   NO    23-05-2018 03:45:11      10000\r\n\r\nSQL&gt; -- Check Synopsis\r\nSQL&gt; SELECT o.name         Table_Name,\r\n       p.subname      Partition_name,\r\n       c.name         &quot;Column&quot;,\r\n       h.analyzetime  &quot;Synopsis Creation Time&quot;\r\nFROM   sys.WRI$_OPTSTAT_SYNOPSIS_HEAD$ h,\r\n       sys.OBJ$ o,\r\n       sys.COL$ c,\r\n       ( ( SELECT TABPART$.bo#  BO#,\r\n                  TABPART$.obj# OBJ#\r\n           FROM   sys.TABPART$ tabpart$ )\r\n         UNION ALL\r\n         ( SELECT TABCOMPART$.bo#  BO#,\r\n                  TABCOMPART$.obj# OBJ#\r\n           FROM   sys.TABCOMPART$ tabcompart$ ) ) tp,\r\n       sys.OBJ$ p\r\nWHERE  o.name = 'T_PART' AND\r\n       tp.obj# = p.obj# AND\r\n       h.bo# = tp.bo# AND\r\n       h.group# = tp.obj# * 2 AND\r\n       h.bo# = c.obj#(+) AND\r\n       h.intcol# = c.intcol#(+) AND\r\n       h.bo# = o.obj#\r\nORDER  BY 4,1,2,3;\r\n\r\nTABLE_NAME PARTITION_ Colum Synopsis Creation Time\r\n---------- ---------- ----- ----------------------\r\nT_PART     SYS_P963   ID                          \r\nT_PART     SYS_P963   PKEY                        \r\nT_PART     SYS_P963   S                           \r\n \r\n<\/pre>\n<p><em><strong>Listing 5 &#8211; explicitly specifying partition in case of interval partitioning <\/strong><\/em><\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>Having representative statistics  (which doesn&#8217;t automatically mean they always have to be fresh though) is essential for ETL Performance. Having looked at some use cases in <a href=\"https:\/\/blog.sqlora.com\/en\/online-statistics-gathering-for-etl-part-1\/\" rel=\"noopener\" target=\"_blank\">part 1<\/a> and <a href=\"https:\/\/blog.sqlora.com\/en\/online-statistics-gathering-for-etl-part-2\/\" rel=\"noopener\" target=\"_blank\">part 2<\/a>, we have seen that there are some specifics to consider.  If you plan to rely on online statistics gathering for some of your ETL steps, better double check that the feature is really working each time you run your ETL process.<\/p>\n<div class=\"crp-list-container\"><h3 class=\"crp-list-title\">Related Posts<\/h3><ul class=\"crp-list\"><li class=\"crp-list-item crp-list-item-image-none\"><div class=\"crp-list-item-title\"><a href=\"https:\/\/blog.sqlora.com\/en\/object-statistics-in-your-data-pipelines\/\" target=\"_blank\">Object Statistics in Your Data Pipelines<\/a><\/div><\/li><li class=\"crp-list-item crp-list-item-image-none\"><div class=\"crp-list-item-title\"><a href=\"https:\/\/blog.sqlora.com\/en\/online-statistics-gathering-for-etl-part-1\/\" target=\"_blank\">Online Statistics Gathering for ETL - Part 1<\/a><\/div><\/li><li class=\"crp-list-item crp-list-item-image-none\"><div class=\"crp-list-item-title\"><a href=\"https:\/\/blog.sqlora.com\/en\/online-statistics-gathering-for-etl-part-3\/\" target=\"_blank\">Online Statistics Gathering for ETL \u2013 Part 3<\/a><\/div><\/li><li class=\"crp-list-item crp-list-item-image-none\"><div class=\"crp-list-item-title\"><a href=\"https:\/\/blog.sqlora.com\/en\/online-statistics-gathering-update-2024\/\" target=\"_blank\">Online Statistics Gathering: Update 2024<\/a><\/div><\/li><\/ul><\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the first part we looked at general preconditions for online statistics gathering to work and some restrictions. In this part we&#8217;ll take a look at what happens with direct path loads into partitioned tables.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,10,50,71,2],"tags":[81,89,83,82,80],"class_list":["post-782","post","type-post","status-publish","format-standard","hentry","category-12c","category-cbo","category-data-warehouse","category-etl","category-oracle","tag-bulk-load","tag-osg","tag-partitioning","tag-piggyback","tag-statistics"],"_links":{"self":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts\/782","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/comments?post=782"}],"version-history":[{"count":9,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts\/782\/revisions"}],"predecessor-version":[{"id":976,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/posts\/782\/revisions\/976"}],"wp:attachment":[{"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/media?parent=782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/categories?post=782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.sqlora.com\/en\/wp-json\/wp\/v2\/tags?post=782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}