{"id":73179,"date":"2014-12-17T18:47:40","date_gmt":"2014-12-17T18:47:40","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/uncategorized\/execution-plans-part-11-actuals\/"},"modified":"2021-07-14T13:07:28","modified_gmt":"2021-07-14T13:07:28","slug":"execution-plans-part-11-actuals","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/execution-plans-part-11-actuals\/","title":{"rendered":"Execution Plans Part 11: Actuals"},"content":{"rendered":"<p>So far in this series we\u2019ve talked about interpreting the shape of an execution plan and understanding the meaning of the predictions that the optimizer has made about <em><strong>cost<\/strong><\/em> and <em><strong>cardinality<\/strong><\/em>. It\u2019s finally time to see how Oracle gives us execution plans that show us how well the optimizer\u2019s estimates match the actual work done as the query ran.<\/p>\n<p>There are three main strategies that we could use to view this information \u2013 enabling <em>\u201crowsource execution statistics\u201d<\/em> then using a call to <em><strong>dbms_xplan.display_cursor()<\/strong><\/em> to display the stats; enabling <em><strong>sql_trace<\/strong><\/em> (which also enables rowsource execution statistics) and reviewing the stats in the <em><strong>tkprof<\/strong><\/em> summaries or even the trace files themselves; or, for those who have licensed the diagnostic and performance packs, enabling <em><strong>SQL Monitoring<\/strong><\/em> and viewing the results (combined with some ASH (<em><strong>v$active_session_history<\/strong><\/em>) information through one of the calls to <em><strong>dbms_sqltune<\/strong><\/em> or through the Enterprise Manager SQL Monitoring screen. In this article we will look at the <em><strong>dbms_xplan.display_cursor()<\/strong><\/em> option.<\/p>\n<h2>Rowsource Execution Statistics<\/h2>\n<p>As a statement executes, Oracle is able to accumulate information about the amount of work done in each operation in the plan, including the number of times each operation has been called, the number of buffers visited, whether the visits were in consistent or current mode, the number of physical reads and (logical) writes, the total time spent in each operation and various bits of information about workarea usage. This information is visible in the dynamic performance view called <em><strong>v$sql_plan_statistics_all<\/strong><\/em>, which, in 11.2.0.4, has the following description:<\/p>\n<pre> 1:\tADDRESS                                   RAW(8)\r\n 2:\tHASH_VALUE                                NUMBER\r\n 3:\tSQL_ID                                    VARCHAR2(13)\r\n 4:\tPLAN_HASH_VALUE                           NUMBER\r\n 5:\tCHILD_ADDRESS                             RAW(8)\r\n 6:\tCHILD_NUMBER                              NUMBER\r\n 7:\tTIMESTAMP                                 DATE\r\n 8:\tOPERATION                                 VARCHAR2(30)\r\n 9:\tOPTIONS                                   VARCHAR2(30)\r\n10:\tOBJECT_NODE                               VARCHAR2(40)\r\n11:\tOBJECT#                                   NUMBER\r\n12:\tOBJECT_OWNER                              VARCHAR2(30)\r\n13:\tOBJECT_NAME                               VARCHAR2(30)\r\n14:\tOBJECT_ALIAS                              VARCHAR2(65)\r\n15:\tOBJECT_TYPE                               VARCHAR2(20)\r\n16:\tOPTIMIZER                                 VARCHAR2(20)\r\n17:\tID                                        NUMBER\r\n18:\tPARENT_ID                                 NUMBER\r\n19:\tDEPTH                                     NUMBER\r\n20:\tPOSITION                                  NUMBER\r\n21:\tSEARCH_COLUMNS                            NUMBER\r\n22:\tCOST                                      NUMBER\r\n23:\tCARDINALITY                               NUMBER\r\n24:\tBYTES                                     NUMBER\r\n25:\tOTHER_TAG                                 VARCHAR2(35)\r\n26:\tPARTITION_START                           VARCHAR2(64)\r\n27:\tPARTITION_STOP                            VARCHAR2(64)\r\n28:\tPARTITION_ID                              NUMBER\r\n29:\tOTHER                                     VARCHAR2(4000)\r\n30:\tDISTRIBUTION                              VARCHAR2(20)\r\n31:\tCPU_COST                                  NUMBER\r\n32:\tIO_COST                                   NUMBER\r\n33:\tTEMP_SPACE                                NUMBER\r\n34:\tACCESS_PREDICATES                         VARCHAR2(4000)\r\n35:\tFILTER_PREDICATES                         VARCHAR2(4000)\r\n36:\tPROJECTION                                VARCHAR2(4000)\r\n37:\tTIME                                      NUMBER\r\n38:\tQBLOCK_NAME                               VARCHAR2(30)\r\n39:\tREMARKS                                   VARCHAR2(4000)\r\n40:\tOTHER_XML                                 CLOB\r\n\r\n41:\tEXECUTIONS                                NUMBER\r\n42:\tLAST_STARTS                               NUMBER\r\n43:\tSTARTS                                    NUMBER\r\n44:\tLAST_OUTPUT_ROWS                          NUMBER\r\n45:\tOUTPUT_ROWS                               NUMBER\r\n46:\tLAST_CR_BUFFER_GETS                       NUMBER\r\n47:\tCR_BUFFER_GETS                            NUMBER\r\n48:\tLAST_CU_BUFFER_GETS                       NUMBER\r\n49:\tCU_BUFFER_GETS                            NUMBER\r\n50:\tLAST_DISK_READS                           NUMBER\r\n51:\tDISK_READS                                NUMBER\r\n52:\tLAST_DISK_WRITES                          NUMBER\r\n53:\tDISK_WRITES                               NUMBER\r\n54:\tLAST_ELAPSED_TIME                         NUMBER\r\n55:\tELAPSED_TIME                              NUMBER\r\n\r\n56:\tPOLICY                                    VARCHAR2(10)\r\n57:\tESTIMATED_OPTIMAL_SIZE                    NUMBER\r\n58:\tESTIMATED_ONEPASS_SIZE                    NUMBER\r\n59:\tLAST_MEMORY_USED                          NUMBER\r\n60:\tLAST_EXECUTION                            VARCHAR2(10)\r\n61:\tLAST_DEGREE                               NUMBER\r\n62:\tTOTAL_EXECUTIONS                          NUMBER\r\n63:\tOPTIMAL_EXECUTIONS                        NUMBER\r\n64:\tONEPASS_EXECUTIONS                        NUMBER\r\n65:\tMULTIPASSES_EXECUTIONS                    NUMBER\r\n66:\tACTIVE_TIME                               NUMBER\r\n67:\tMAX_TEMPSEG_SIZE                          NUMBER\r\n68:\tLAST_TEMPSEG_SIZE                         NUMBER<\/pre>\n<p>If you check through this list of columns you\u2019ll notice that the first 40 columns are just repeating <em><strong>v$sql_plan<\/strong><\/em> \u2013 the basic in-memory execution plan information \u2013 then lines 41 \u2013 55 are the non-key columns from <em><strong>v$sql_plan_statistics<\/strong><\/em>, and lines 56 \u2013 68 are from <em><strong>v$sql_workarea<\/strong><\/em>. The appearance of the last set of columns, of course, means that a query against <em><strong>v$sql_plan_statistics_all<\/strong><\/em> will report some useful information (the work area information) even when you haven\u2019t enabled rowsource execution statistics.<\/p>\n<h2>Workarea<\/h2>\n<p>Before we pursue\u00a0<em><strong>v$sql_plan_statistics_all<\/strong><\/em>, it\u2019s worth making a couple of comments about how we can take advantage of the information available in <em><strong>v$sql_workarea<\/strong><\/em> because it\u2019s a view that\u2019s often overlooked in troubleshooting. Let\u2019s start with a simple query against the sys schema, followed by a call to <em><strong>dbms_xplan.display_cursor()<\/strong><\/em> \u2013 when we haven&#8217;t enabled rowsource execution statistics:<\/p>\n<pre>alter session set statistics_level = typical;\r\n\r\nselect ct, count(*) from (\r\n\tselect obj#, count(*) ct from sys.source$ group by obj#\r\n) \r\ngroup by ct order by ct\r\n\r\nselect * from table(dbms_xplan.display_cursor(null,null,'allstats last'))\r\n\r\nSQL_ID  33vchu53wj57a, child number 0\r\n-------------------------------------\r\nselect ct, count(*) from (select obj#, count(*) ct from sys.source$\r\ngroup by obj#) group by ct order by ct\r\n\r\nPlan hash value: 2879348764\r\n\r\n---------------------------------------------------------------------------------\r\n| Id  | Operation               | Name      | E-Rows |  OMem |  1Mem | Used-Mem |\r\n---------------------------------------------------------------------------------\r\n|   0 | SELECT STATEMENT        |           |        |       |       |          |\r\n|   1 |  SORT GROUP BY          |           |   5513 | 36864 | 36864 |32768  (0)|\r\n|   2 |   VIEW                  |           |   5513 |       |       |          |\r\n|   3 |    HASH GROUP BY        |           |   5513 |    37M|  8100K| 2719K (0)|\r\n|   4 |     INDEX FAST FULL SCAN| I_SOURCE1 |    670K|       |       |          |\r\n---------------------------------------------------------------------------------\r\n\r\nNote\r\n-----\r\n   - Warning: basic plan statistics not available. These are only collected when:\r\n       * hint 'gather_plan_statistics' is used for the statement or\r\n       * parameter 'statistics_level' is set to 'ALL', at session or system level<\/pre>\n<p>In the call to <em><strong>display_cursor()<\/strong><\/em> I\u2019ve used the parameter values <em>(null, null, \u2018allstats last\u2019)<\/em>. This should report the rowsource execution statistics for the last execution of the last statement I\u2019ve run \u2013 but I\u2019ve set statistics_level to \u201ctypical\u201d (the default) so there are no execution statistics available other than those related to wokarea (PGA) usage. As a side effect of this the <em><strong>Note<\/strong><\/em> section of the output contains a warning that the statistics are not available then tells us about the two (official) methods of enabling them (there is a third, which is to set the hidden parameter <em><strong>_rowsource_execution_statistics<\/strong><\/em> to true).<\/p>\n<p style=\"padding-left: 30px\"><em>Reminder: if you are using <strong>dbms_xplan.display_cursor()<\/strong> to report the last plan of the last statement you executed from SQL*Plus, don\u2019t forget that you need to \u201cset serveroutput off\u201d before you begin, otherwise the last statement will be dbms_output.get_lines() and Oracle will complain that it \u201ccannot fetch plan for SQL_ID: 9babjv8yq8ru3\u201d. (A similar complaint \u2013 different SQL_ID &#8211; may arise occasionally, and apparently randomly, if the statement you are investigating had to be re-optimised during the test.)<\/em><\/p>\n<p>For the \u201clast\u201d execution option the workarea stats we get are:<\/p>\n<ul>\n<li>OMem: \u00a0The memory Oracle thinks we would need to operate completely in memory.<\/li>\n<li>1Mem: \u00a0The memory above which we could still manage to do a one-pass workarea operation<\/li>\n<li>Used-Mem: \u00a0The actual memory we used on the last execution<\/li>\n<\/ul>\n<p>If we change the call to dbms_xplan to use <em>\u2018allstats\u2019<\/em> rather than <em>\u2018allstats last\u2019<\/em>, we get a summary of activity for the child cursor since it was first executed; in my case:<\/p>\n<pre>---------------------------------------------------------------------------------\r\n| Id  | Operation               | Name      | E-Rows |  OMem |  1Mem |  O\/1\/M   |\r\n---------------------------------------------------------------------------------\r\n|   0 | SELECT STATEMENT        |           |        |       |       |          |\r\n|   1 |  SORT GROUP BY          |           |   5513 | 36864 | 36864 |     2\/0\/0|\r\n|   2 |   VIEW                  |           |   5513 |       |       |          |\r\n|   3 |    HASH GROUP BY        |           |   5513 |    37M|  8100K|     2\/0\/0|\r\n|   4 |     INDEX FAST FULL SCAN| I_SOURCE1 |    670K|       |       |          |\r\n---------------------------------------------------------------------------------<\/pre>\n<p>The final column now reports the number of times each operation performed as an optimal (in-memory) execution, how many as a one-pass, and how many went multi-pass. In this case (having run the query twice) I had two optimal executions, and no operations spilling to disc. Unfortunately my version of Oracle seemed to have some bugs in this area showing (for example) a blank entry for the <em><strong>O\/1\/M<\/strong><\/em> column at line 3 when it had done a couple of one-pass executions for the <em>&#8220;hash group by&#8221;<\/em>. When this happened, though, the plan did give some clue about the spill to disc because it reported the amount of disc space used in a <em><strong>Used-Tmp<\/strong><\/em> column (with the \u201clast\u201d option) or a <em><strong>Max-Tmp<\/strong><\/em> column. (In passing, the &#8220;temporary space&#8221; columns report the number of KB used but, unlike the &#8220;memory&#8221; columns, don\u2019t include a K to remind you of the fact.)<\/p>\n<p>To take best advantage of the <em><strong>v$sql_workarea<\/strong><\/em> view in combination with <em><strong>dbms_xplan.display_cursor()<\/strong><\/em> you can query the view to find interesting statement with a query like:<\/p>\n<pre>select\r\n        sql_id, child_number, estimated_optimal_size,\r\n        total_executions, optimal_executions, onepass_executions, multipasses_executions,\r\n        max_tempseg_size\r\nfrom\r\n        v$sql_workarea\r\nwhere\r\n        max_tempseg_size &gt; 65535\r\nor      onepass_executions &gt; 10\r\nor      multipasses_executions &gt; 0\r\n;<\/pre>\n<p>After running this query you can use any reported sql_ids and child_numbers in a call to <em><strong>dbms_xplan.display_cursor()<\/strong><\/em> to get the SQL and plan for any statements that might be imposing a large strain on your system resources. Another strategy (if you are prompt enough) would be to pass in the sql_id (with an explicit null for the child number) for any interesting SQL ids that you have picked from a very recent AWR or Statspack report \u2013 with a little luck the plan and workarea stats might still be in memory. It&#8217;s important to remember, though, that this query will be doing a brute-force scan through your entire library cache, so it&#8217;s not a query you should run frequently, especially if you have a large SGA, the overheads on latch and mutex acquisition could be significant. (I probably wouldn&#8217;t run it more than four or five times per hour.)<\/p>\n<h2>Execution Stats<\/h2>\n<p>When I enabled rowsource execution statistics by setting <em><strong>statistics_level<\/strong><\/em> to all there were two significant changes to my tests. First the execution time jumped from 0.12 seconds to 3.75 seconds (most of it CPU); secondly the output of <em><strong>dbms_xplan.display_cursor()<\/strong><\/em> produced a lot more columns:<\/p>\n<pre>------------------------------------------------------------------------------------------------------------------------------------------------------\r\n| Id  | Operation               | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  | Writes |  OMem |  1Mem | Used-Mem | Used-Tmp|\r\n------------------------------------------------------------------------------------------------------------------------------------------------------\r\n|   0 | SELECT STATEMENT        |           |      1 |        |    563 |00:00:03.73 |    1623 |   1632 |     16 |       |       |          |         |\r\n|   1 |  SORT GROUP BY          |           |      1 |   5513 |    563 |00:00:03.73 |    1623 |   1632 |     16 | 37888 | 37888 |32768  (0)|         |\r\n|   2 |   VIEW                  |           |      1 |   5513 |   5514 |00:00:03.71 |    1623 |   1632 |     16 |       |       |          |         |\r\n|   3 |    HASH GROUP BY        |           |      1 |   5513 |   5514 |00:00:03.69 |    1623 |   1632 |     16 |    36M|  8304K|  421K (0)|    1024 |\r\n|   4 |     INDEX FAST FULL SCAN| I_SOURCE1 |      1 |    670K|    670K|00:00:01.84 |    1623 |   1616 |      0 |       |       |          |         |\r\n------------------------------------------------------------------------------------------------------------------------------------------------------<\/pre>\n<p>The extra CPU is platform dependent and relates the time spent on calls to the O\/S timing functions; and for this reason you may want to do a little testing for your own platform and may want to switch to an alternative mechanism for enabling the stats. As we saw in the <em>\u2018Note\u2019<\/em> section of an earlier plan, adding the hint <em><strong>\/*+ gather_plan_statistics *\/<\/strong><\/em> to a query will enable the collection; but when the stats are driven by the hint the timing is done by <strong>sampling<\/strong> which, in my case, meant the query took 0.18 seconds (compared to 0.12 or 3.75 seconds). There is a catch, of course; here\u2019s the final output hinted when I set the statistics_level back to typical and hinted the stats collection:<\/p>\n<pre>------------------------------------------------------------------------------------------------------------------------------------------------------\r\n| Id  | Operation               | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  | Writes |  OMem |  1Mem | Used-Mem | Used-Tmp|\r\n------------------------------------------------------------------------------------------------------------------------------------------------------\r\n|   0 | SELECT STATEMENT        |           |      1 |        |    563 |00:00:00.15 |    1623 |     42 |     16 |       |       |          |         |\r\n|   1 |  SORT GROUP BY          |           |      1 |   5513 |    563 |00:00:00.15 |    1623 |     42 |     16 | 37888 | 37888 |32768  (0)|         |\r\n|   2 |   VIEW                  |           |      1 |   5513 |   5514 |00:00:00.21 |    1623 |     42 |     16 |       |       |          |         |\r\n|   3 |    HASH GROUP BY        |           |      1 |   5513 |   5514 |00:00:00.17 |    1623 |     42 |     16 |    36M|  8304K|  431K (0)|    1024 |\r\n|   4 |     INDEX FAST FULL SCAN| I_SOURCE1 |      1 |    670K|    670K|00:00:02.31 |    1623 |     26 |      0 |       |       |          |         |\r\n------------------------------------------------------------------------------------------------------------------------------------------------------<\/pre>\n<p>The change in <em><strong>Reads<\/strong><\/em> is a side effect of normal data caching, but look at the <em><strong>A-Time<\/strong><\/em> column in these two examples \u2013 this is supposed to accumulate up the plan from child to parent and something has clearly gone wrong. This plan is very simple \u2013 each operation calls the one below it\u00a0\u2013\u00a0so we should see a simple accumulation up the plan; but the <em><strong>index fast full scan<\/strong><\/em>\u00a0(the first operation to produce a rowsource) reports 2.31 seconds spent in a query that totaled 0.18 seconds; and the accumulated times go up and down as we work up the plan. If you use the <em><strong>\/*+ gather_plan_statistics *\/<\/strong><\/em> hint to enable rowsource execution statistics you cannot trust the accuracy of the <em><strong>A-Time<\/strong><\/em> column.<\/p>\n<p>We jumped the gun a little with the explanation of the A-Time column, but here\u2019s a reference to the rest of the columns relating to execution statistics:<\/p>\n<ul>\n<li>Starts: \u00a0The number of times this operation actually occurred<\/li>\n<li>E-rows: \u00a0Estimated rows (per execution of the operation) \u2013 i.e. the \u201cRows\u201d column from a call to display()<\/li>\n<li>A-rows: \u00a0The accumulated number of rows forwarded by this operation<\/li>\n<li>A-time: \u00a0The accumulated time spent in this operation \u2013 including time spent in its descendents.<\/li>\n<li>Buffers: \u00a0Accumulated buffer visits made by this operation \u2013 including its descendents.<\/li>\n<li>Reads: \u00a0Accumulated number of blocks read from disc by this operation \u2013 including its descendents.<\/li>\n<li>Writes: \u00a0Accumulated number of blocks written to disc by this operation \u2013 including its descendents.<\/li>\n<\/ul>\n<p>There are two critical points to remember when interpreting a plan with execution stats; the first is understanding what it means to say that Oracle <em>\u2018accumulates\u2019<\/em> up the plan, the second is the significance of the <em><strong>Starts<\/strong><\/em> column.<\/p>\n<h2>Interpretation<\/h2>\n<p>The sample SQL I\u2019ve supplied for this article isn\u2019t ideal for helping us to appreciate either point \u2013 and I\u2019ll be using better examples in the next couple of articles \u2013 but we can at least see some signs of the accumulation feature.<\/p>\n<p>One of the better rules of thumb for reading execution plans is the sound-bite <em>\u2018first child first\u2019<\/em> \u2013 a parent operation calls each of its child operations in turn, then allows for recursive descent as each child may call its direct descendants before returning rows to the parent. With this in mind it\u2019s easy to appreciate that the work done <em>\u2018by an operation\u2019<\/em> consists of the work the operation does in its own right (e.g. sorting incoming data) plus the work done by each of its children in supplying data to it.<\/p>\n<p>The example doesn\u2019t show any parent operations with multiple children, but we can see a simple example of this <em>\u2018parent plus children\u2019<\/em> algorithm in operations 3 and 4 above. A <em>\u201chash group by\u201d<\/em> doesn\u2019t, inherently, use the buffer cache, so line 3 can\u2019t be responsible for the 1,623 buffer gets recorded \u2013 but they appeared at operation 4, the child to line 3 that produced the rowsource for line 3 to aggregate.<\/p>\n<p>On the other hand, if a \u201chash group by\u201d spills to disc it will do some writes to the temporary tablespace and then read them back. Operation 3 reports 16 blocks written and 42 blocks read, but how can there be more reads than writes \u2013 the excess of 26 is the 26 reads performed at operation 4 during the fast full scan of index <em><strong>i_source1<\/strong><\/em>.<\/p>\n<p>From there on upwards the plan shows no incremental use of resources (the \u201csort group by\u201d of operation 1 completes in memory so there are no further reads and writes).<\/p>\n<p>The significance of the <strong>Starts<\/strong> column isn\u2019t really visible in this plan since each operation starts only once. We will examine the column more closely in the next article but for the moment I\u2019ll just point out that the <em><strong>E-rows<\/strong><\/em> (estimated) and <em><strong>A-rows<\/strong><\/em> (actual) are a very good match for most of the operations in this example, and we should be happy with that since it shows that the optimizer has (right up until the last operation) made a good prediction about the volume of data processed by our query. But the close match in the two columns is only there because the <em><strong>Starts<\/strong><\/em> column holds the value 1: <em><strong>E-rows<\/strong><\/em> is the estimated rows <strong>per execution<\/strong> of the operation, so when we are trying to assess the accuracy of the optimizer\u2019s predictions we generally need to compare <em><strong>A-Rows<\/strong><\/em> with <em><strong>E-rows * Starts<\/strong><\/em>\u00a0and (as we shall see in the next article) we still have to be careful about deciding when that is a useful comparison and when it is meaningless.<\/p>\n<h2>Summary<\/h2>\n<p>In this article we focused on one of the three basic strategies for acquiring rowsource execution statistics \u2013 pausing on the way to point out that one component of the full set (<em><strong>v$sql_workarea<\/strong><\/em>) can point us towards interesting SQL before we\u2019ve even started looking in detail at any specific SQL.<\/p>\n<p>We\u2019ve looked in some detail at the way in which we can use the fundamental view <em><strong>v$sql_plan_statistics_all<\/strong><\/em>, and highlighted a potential performance threat that you need to check for on your specific platforms.<\/p>\n<p>Finally, we\u2019ve discussed how to interpret the numbers that appear when we report the statistics \u2013 though we need to look at a more complex example to appreciate fully the significance of the <em><strong>Starts<\/strong><\/em> column when trying to use the rowsource execution statistics as an aid to solving performance problems.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So far in this series we\u2019ve talked about interpreting the shape of an execution plan and understanding the meaning of the predictions that the optimizer has made about cost and cardinality. It\u2019s finally time to see how Oracle gives us execution plans that show us how well the optimizer\u2019s estimates match the actual work done as the query ran. Ther&hellip;<\/p>\n","protected":false},"author":101205,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143533],"tags":[4783,4150,5296],"coauthors":[],"class_list":["post-73179","post","type-post","status-publish","format-standard","hentry","category-oracle-databases","tag-execution-plans","tag-sql","tag-statistics"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/73179","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/101205"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=73179"}],"version-history":[{"count":1,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/73179\/revisions"}],"predecessor-version":[{"id":91668,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/73179\/revisions\/91668"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=73179"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=73179"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=73179"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=73179"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}