{"action":"created","issue":{"url":"https://api.github.com/repos/pingcap/tidb/issues/7827","repository_url":"https://api.github.com/repos/pingcap/tidb","labels_url":"https://api.github.com/repos/pingcap/tidb/issues/7827/labels{/name}","comments_url":"https://api.github.com/repos/pingcap/tidb/issues/7827/comments","events_url":"https://api.github.com/repos/pingcap/tidb/issues/7827/events","html_url":"https://github.com/pingcap/tidb/pull/7827","id":365734362,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE5NTgwOTA5","number":7827,"title":"*: make `explain` support `explain anaylze`","user":{"login":"lysu","id":528332,"node_id":"MDQ6VXNlcjUyODMzMg==","avatar_url":"https://avatars3.githubusercontent.com/u/528332?v=4","gravatar_id":"","url":"https://api.github.com/users/lysu","html_url":"https://github.com/lysu","followers_url":"https://api.github.com/users/lysu/followers","following_url":"https://api.github.com/users/lysu/following{/other_user}","gists_url":"https://api.github.com/users/lysu/gists{/gist_id}","starred_url":"https://api.github.com/users/lysu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lysu/subscriptions","organizations_url":"https://api.github.com/users/lysu/orgs","repos_url":"https://api.github.com/users/lysu/repos","events_url":"https://api.github.com/users/lysu/events{/privacy}","received_events_url":"https://api.github.com/users/lysu/received_events","type":"User","site_admin":false},"labels":[{"id":799107676,"node_id":"MDU6TGFiZWw3OTkxMDc2NzY=","url":"https://api.github.com/repos/pingcap/tidb/labels/component/tools","name":"component/tools","color":"cbf232","default":false},{"id":258976663,"node_id":"MDU6TGFiZWwyNTg5NzY2NjM=","url":"https://api.github.com/repos/pingcap/tidb/labels/proposal","name":"proposal","color":"eb6420","default":false},{"id":257593099,"node_id":"MDU6TGFiZWwyNTc1OTMwOTk=","url":"https://api.github.com/repos/pingcap/tidb/labels/status/WIP","name":"status/WIP","color":"fbca04","default":false},{"id":770872605,"node_id":"MDU6TGFiZWw3NzA4NzI2MDU=","url":"https://api.github.com/repos/pingcap/tidb/labels/status/all%20tests%20passed","name":"status/all tests passed","color":"2cbe4e","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2018-10-02T04:13:55Z","updated_at":"2018-10-08T02:05:30Z","closed_at":null,"author_association":"MEMBER","pull_request":{"url":"https://api.github.com/repos/pingcap/tidb/pulls/7827","html_url":"https://github.com/pingcap/tidb/pull/7827","diff_url":"https://github.com/pingcap/tidb/pull/7827.diff","patch_url":"https://github.com/pingcap/tidb/pull/7827.patch"},"body":"### What problem does this PR solve? <!--add issue link with summary if exists-->\r\n\r\nCurrently, our `explain` command only display the physical plan result without execution.\r\n\r\nbut sometime we also need execution info to help us find reality plan question or executor performance bottleneck.\r\n\r\nthis PR add `anaylze` option to `explain` command(it just like postgresql's `explain anaylze` does https://www.postgresql.org/docs/9.1/static/sql-explain.html), and it  will cause the statement to be actually executed, not only planned.\r\n\r\nit works like this:\r\n\r\n```\r\nmysql> explain analyze select a_id, count(*) from v left join `u` on `u`.id = v.u_id where p_id = 1 and `u`.t > '2018-08-01' and v.t>'2018-08-01' group by a_id;\r\n+------------------------------+---------+------+---------------------------------------------------------------------------------------+---------------------------------------+\r\n| id                           | count   | task | operator info                                                                         | execution_info                        |\r\n+------------------------------+---------+------+---------------------------------------------------------------------------------------+---------------------------------------+\r\n| Projection_7                 | 2.67    | root | test.v.a_id, 5_col_0                                                          | actual_time:0.504215, loops:1, rows:0 |\r\n| └─HashAgg_10                 | 2.67    | root | group by:test.v.a_id, funcs:count(1), firstrow(test.v.a_id)           | actual_time:0.497296, loops:1, rows:0 |\r\n|   └─IndexJoin_18             | 4.17    | root | inner join, inner:TableReader_17, outer key:test.v.u_id, inner key:test.u.id | actual_time:0.394209, loops:1, rows:0 |\r\n|     ├─IndexLookUp_40         | 3.33    | root |                                                                                       | actual_time:0.365342, loops:1, rows:0 |\r\n|     │ ├─IndexScan_37         | 10.00   | cop  | table:v, index:p_id, u_id, range:[1,1], keep order:false, stats:pseudo       | actual_time:0.000000, loops:0, rows:0 |\r\n|     │ └─Selection_39         | 3.33    | cop  | gt(test.v.t, 2018-08-01 00:00:00.000000)                                | actual_time:0.000000, loops:0, rows:0 |\r\n|     │   └─TableScan_38       | 10.00   | cop  | table:v, keep order:false, stats:pseudo                                            | actual_time:0.000000, loops:0, rows:0 |\r\n|     └─TableReader_17         | 3333.33 | root | data:Selection_16                                                                     | actual_time:0.000000, loops:0, rows:0 |\r\n|       └─Selection_16         | 3333.33 | cop  | gt(test.u.t, 2018-08-01 00:00:00.000000)                                | actual_time:0.000000, loops:0, rows:0 |\r\n|         └─TableScan_15       | 10.00   | cop  | table:u, range: decided by [test.v.u_id], keep order:false, stats:pseudo     | actual_time:0.000000, loops:0, rows:0 |\r\n+------------------------------+---------+------+---------------------------------------------------------------------------------------+---------------------------------------+\r\n10 rows in set (0.00 sec)\r\n```\r\n\r\nthe difference is with addition `execution_info` columns, and has be actual executed.\r\n\r\n### What is changed and how it works?\r\n\r\n- change `Executor`'s `Next` from method to a func field to make it bindable\r\n- bind  \"Normal version Next\" or \"Explain version Next\"  once in plan build phase\r\n- maintain ExecStats(a map), and init ExecStates entry in plan building phase(single thread, so map itself no race condition, but for entry...)\r\n- add switch on `SessionCtx.StmtCtx` level to control Normal or Explain execution\r\n- modify `Explain` to open switch then actual execute plan and output addition column.\r\n\r\n### Remain question\r\n\r\n- StatsEntry race condtion in some executor\r\n- Cop task need get info from tikv\r\n\r\n### Check List <!--REMOVE the items that are not applicable-->\r\n\r\nTests <!-- At least one of them must be included. -->\r\n\r\n-  Old test\r\n - Manual test (add detailed scripts or steps below)\r\n\r\nCode changes\r\n\r\n - Has exported function/method change\r\n - Has exported variable/fields change\r\n - Has interface methods change\r\n\r\nSide effects\r\n\r\n - Possible performance regression\r\n\r\nRelated changes\r\n\r\n - Need to update the documentation\r\n - Need to be included in the release note\r\n\r\n<!-- Reviewable:start -->\r\n---\r\nThis change is [<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/pingcap/tidb/7827)\r\n<!-- Reviewable:end -->\r\n"},"comment":{"url":"https://api.github.com/repos/pingcap/tidb/issues/comments/427706692","html_url":"https://github.com/pingcap/tidb/pull/7827#issuecomment-427706692","issue_url":"https://api.github.com/repos/pingcap/tidb/issues/7827","id":427706692,"node_id":"MDEyOklzc3VlQ29tbWVudDQyNzcwNjY5Mg==","user":{"login":"zz-jason","id":5268763,"node_id":"MDQ6VXNlcjUyNjg3NjM=","avatar_url":"https://avatars0.githubusercontent.com/u/5268763?v=4","gravatar_id":"","url":"https://api.github.com/users/zz-jason","html_url":"https://github.com/zz-jason","followers_url":"https://api.github.com/users/zz-jason/followers","following_url":"https://api.github.com/users/zz-jason/following{/other_user}","gists_url":"https://api.github.com/users/zz-jason/gists{/gist_id}","starred_url":"https://api.github.com/users/zz-jason/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zz-jason/subscriptions","organizations_url":"https://api.github.com/users/zz-jason/orgs","repos_url":"https://api.github.com/users/zz-jason/repos","events_url":"https://api.github.com/users/zz-jason/events{/privacy}","received_events_url":"https://api.github.com/users/zz-jason/received_events","type":"User","site_admin":false},"created_at":"2018-10-08T02:05:30Z","updated_at":"2018-10-08T02:05:30Z","author_association":"MEMBER","body":"@lysu we don't need to bind different `next()` functions. we only need to add a `if` statement in the `next()` function for every operator to record the executor statistics. and these executor statistics can also be reused in the `trace` statement."}}
{"actor":{"display_login":"zz-jason"}}