Skip to content

Commit

Permalink
refine: add binary_plan_json and re-implement binary_plan_text
Browse files Browse the repository at this point in the history
  • Loading branch information
baurine committed Aug 11, 2023
1 parent f2d8a6d commit 5ac762b
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 40 deletions.
13 changes: 8 additions & 5 deletions pkg/apiserver/slowquery/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ type Model struct {
TxnStartTS string `gorm:"column:Txn_start_ts" json:"txn_start_ts"`

// Detail
PrevStmt string `gorm:"column:Prev_stmt" json:"prev_stmt"`
Plan string `gorm:"column:Plan" json:"plan"` // deprecated, replaced by BinaryPlanText
BinaryPlan string `gorm:"column:Binary_plan" json:"binary_plan"`
BinaryPlanText string `gorm:"column:Binary_plan_text" proj:"tidb_decode_binary_plan(Binary_plan)" json:"binary_plan_text"`
Warnings datatypes.JSON `gorm:"column:Warnings" json:"warnings"`
PrevStmt string `gorm:"column:Prev_stmt" json:"prev_stmt"`
Plan string `gorm:"column:Plan" json:"plan"` // deprecated, replaced by BinaryPlanText
BinaryPlan string `gorm:"column:Binary_plan" json:"binary_plan"`
Warnings datatypes.JSON `gorm:"column:Warnings" json:"warnings"`

// Basic
IsInternal int `gorm:"column:Is_internal" json:"is_internal"`
Expand Down Expand Up @@ -96,6 +95,10 @@ type Model struct {
RocksdbBlockCacheHitCount uint `gorm:"column:Rocksdb_block_cache_hit_count" json:"rocksdb_block_cache_hit_count"`
RocksdbBlockReadCount uint `gorm:"column:Rocksdb_block_read_count" json:"rocksdb_block_read_count"`
RocksdbBlockReadByte uint `gorm:"column:Rocksdb_block_read_byte" json:"rocksdb_block_read_byte"`

// Computed fields
BinaryPlanJSON string `json:"binary_plan_json"` // binary plan json format
BinaryPlanText string `json:"binary_plan_text"` // binary plan plain text
}

type Field struct {
Expand Down
10 changes: 1 addition & 9 deletions pkg/apiserver/slowquery/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,19 +109,11 @@ func QuerySlowLogList(req *GetListRequest, sysSchema *utils.SysSchema, db *gorm.
func QuerySlowLogDetail(req *GetDetailRequest, db *gorm.DB) (*Model, error) {
var result Model
err := db.
Select("*, (UNIX_TIMESTAMP(Time) + 0E0) AS timestamp, tidb_decode_binary_plan(Binary_plan) AS Binary_plan_text").
Select("*, (UNIX_TIMESTAMP(Time) + 0E0) AS timestamp").
Where("Digest = ?", req.Digest).
Where("Time = FROM_UNIXTIME(?)", req.Timestamp).
Where("Conn_id = ?", req.ConnectID).
First(&result).Error
if err != nil {
err = db.
Select("*, (UNIX_TIMESTAMP(Time) + 0E0) AS timestamp").
Where("Digest = ?", req.Digest).
Where("Time = FROM_UNIXTIME(?)", req.Timestamp).
Where("Conn_id = ?", req.ConnectID).
First(&result).Error
}
if err != nil {
return nil, err
}
Expand Down
13 changes: 11 additions & 2 deletions pkg/apiserver/slowquery/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,23 @@ func (s *Service) getDetails(c *gin.Context) {
return
}

// generate binary plan
// generate binary plan json
//
// Due to a kernel bug, the binary plan may fail to parse due to
// encoding issues. Additionally, since the binary plan field is
// not a required field, we can mask this error.
//
// See: https://github.com/pingcap/tidb-dashboard/issues/1515
result.BinaryPlan, _ = utils.GenerateBinaryPlanJSON(result.BinaryPlan)
if result.BinaryPlan != "" {
// may failed but it's ok
result.BinaryPlanText, _ = utils.GenerateBinaryPlanText(db, result.BinaryPlan)
// may failed but it's ok
result.BinaryPlanJSON, _ = utils.GenerateBinaryPlanJSON(result.BinaryPlan)

// reduce response size
result.BinaryPlan = ""
result.Plan = ""
}

Check warning on line 119 in pkg/apiserver/slowquery/service.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiserver/slowquery/service.go#L110-L119

Added lines #L110 - L119 were not covered by tests

c.JSON(http.StatusOK, *result)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/apiserver/statement/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,8 @@ type Model struct {
AggIndexNames string `json:"index_names" agg:"ANY_VALUE(index_names)"`
AggPlanCount int `json:"plan_count" agg:"COUNT(DISTINCT plan_digest)" related:"plan_digest"`
AggPlan string `json:"plan" agg:"ANY_VALUE(plan)"` // deprecated, replaced by BinaryPlanText
AggPlanDigest string `json:"plan_digest" agg:"ANY_VALUE(plan_digest)"`
AggBinaryPlan string `json:"binary_plan" agg:"ANY_VALUE(binary_plan)"`
AggBinaryPlanText string `json:"binary_plan_text" related:"binary_plan" agg:"tidb_decode_binary_plan(ANY_VALUE(binary_plan))"`
AggPlanDigest string `json:"plan_digest" agg:"ANY_VALUE(plan_digest)"`
AggPlanHint *string `json:"plan_hint" agg:"ANY_VALUE(plan_hint)"`
// RocksDB
AggMaxRocksdbDeleteSkippedCount uint `json:"max_rocksdb_delete_skipped_count" agg:"MAX(max_rocksdb_delete_skipped_count)"`
Expand All @@ -99,6 +98,8 @@ type Model struct {
// Computed fields
RelatedSchemas string `json:"related_schemas"`
PlanCanBeBound bool `json:"plan_can_be_bound"`
BinaryPlanJSON string `json:"binary_plan_json"`
BinaryPlanText string `json:"binary_plan_text"`
}

// tableNames example: "d1.a1,d2.a2,d1.a1,d3.a3"
Expand Down
13 changes: 10 additions & 3 deletions pkg/apiserver/statement/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,16 @@ func (s *Service) planDetailHandler(c *gin.Context) {
return
}

// get binary plan
// may failed but it's ok
result.AggBinaryPlan, _ = utils.GenerateBinaryPlanJSON(result.AggBinaryPlan)
if result.AggBinaryPlan != "" {
// may failed but it's ok
result.BinaryPlanText, _ = utils.GenerateBinaryPlanText(db, result.AggBinaryPlan)
// may failed but it's ok
result.BinaryPlanJSON, _ = utils.GenerateBinaryPlanJSON(result.AggBinaryPlan)

// reduce response size
result.AggBinaryPlan = ""
result.AggPlan = ""
}

Check warning on line 245 in pkg/apiserver/statement/service.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiserver/statement/service.go#L236-L245

Added lines #L236 - L245 were not covered by tests

c.JSON(http.StatusOK, result)
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/apiserver/utils/binary_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/pingcap/tipb/go-tipb"
json "google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/runtime/protoimpl"
"gorm.io/gorm"
)

const (
Expand Down Expand Up @@ -975,3 +976,17 @@ func formatJSON(s string) (*simplejson.Json, error) {

return simplejson.NewJson([]byte(s))
}

/////////////////

func GenerateBinaryPlanText(db *gorm.DB, b string) (string, error) {
type binaryPlanText struct {
Text string `gorm:"column:binary_plan_text"`
}
ret := &binaryPlanText{}
err := db.Raw(fmt.Sprintf("select tidb_decode_binary_plan('%s') as binary_plan_text", b)).Find(ret).Error
if err != nil {
return "", err
}
return ret.Text, err

Check warning on line 991 in pkg/apiserver/utils/binary_plan.go

View check run for this annotation

Codecov / codecov/patch

pkg/apiserver/utils/binary_plan.go#L982-L991

Added lines #L982 - L991 were not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ export interface SlowqueryModel {
*/
'binary_plan'?: string;
/**
*
* Computed fields
* @type {string}
* @memberof SlowqueryModel
*/
'binary_plan_json'?: string;
/**
* binary plan plain text
* @type {string}
* @memberof SlowqueryModel
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ export interface StatementModel {
* @memberof StatementModel
*/
'binary_plan'?: string;
/**
*
* @type {string}
* @memberof StatementModel
*/
'binary_plan_json'?: string;
/**
*
* @type {string}
Expand Down
8 changes: 8 additions & 0 deletions ui/packages/tidb-dashboard-client/swagger/spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -4906,7 +4906,12 @@
"binary_plan": {
"type": "string"
},
"binary_plan_json": {
"description": "Computed fields",
"type": "string"
},
"binary_plan_text": {
"description": "binary plan plain text",
"type": "string"
},
"commit_backoff_time": {
Expand Down Expand Up @@ -5314,6 +5319,9 @@
"binary_plan": {
"type": "string"
},
"binary_plan_json": {
"type": "string"
},
"binary_plan_text": {
"type": "string"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useContext } from 'react'
import React, { useState, useContext, useMemo } from 'react'
import { Space, Modal, Tabs, Typography } from 'antd'
import { useTranslation } from 'react-i18next'
import { useLocation, useNavigate } from 'react-router-dom'
Expand Down Expand Up @@ -56,7 +56,13 @@ function DetailPage() {
)
)

const binaryPlan = data?.binary_plan && JSON.parse(data.binary_plan)
const binaryPlanObj = useMemo(() => {
const json = data?.binary_plan_json ?? data?.binary_plan
if (json) {
return JSON.parse(json)
}
return undefined
}, [data?.binary_plan, data?.binary_plan_json])

const [detailExpand, setDetailExpand] = useVersionedLocalStorageState(
SLOW_QUERY_DETAIL_EXPAND,
Expand Down Expand Up @@ -167,7 +173,7 @@ function DetailPage() {
)
})()}
</Descriptions>
{(binaryPlan || !!data.plan) && (
{(binaryPlanObj || !!data.plan) && (
<>
<Space size="middle" style={{ color: '#8c8c8c' }}>
{t('slow_query.detail.plan.title')}
Expand Down Expand Up @@ -206,17 +212,17 @@ function DetailPage() {
</Descriptions>
</Tabs.TabPane>

{binaryPlan && !binaryPlan.discardedDueToTooLong && (
{binaryPlanObj && !binaryPlanObj.discardedDueToTooLong && (
<Tabs.TabPane
tab={t('slow_query.detail.plan.table')}
key="binary_plan_table"
>
<BinaryPlanTable data={binaryPlan} />
<BinaryPlanTable data={binaryPlanObj} />
<div style={{ height: 24 }} />
</Tabs.TabPane>
)}

{binaryPlan && !binaryPlan.discardedDueToTooLong && (
{binaryPlanObj && !binaryPlanObj.discardedDueToTooLong && (
<Tabs.TabPane
tab={t('slow_query.detail.plan.visual')}
key="binary_plan"
Expand All @@ -234,12 +240,12 @@ function DetailPage() {
height: window.innerHeight - 100
}}
>
<VisualPlanView data={binaryPlan} />
<VisualPlanView data={binaryPlanObj} />
</Modal>
<Descriptions>
<Descriptions.Item span={2}>
<div onClick={() => toggleVisualPlan('open')}>
<VisualPlanThumbnailView data={binaryPlan} />
<VisualPlanThumbnailView data={binaryPlanObj} />
</div>
</Descriptions.Item>
</Descriptions>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useContext } from 'react'
import React, { useState, useContext, useMemo } from 'react'
import { Space, Tabs, Modal } from 'antd'
import { useTranslation } from 'react-i18next'
import {
Expand Down Expand Up @@ -62,7 +62,13 @@ function PlanDetail({ query }: IPlanDetailProps) {
)
const isLoading = isDataLoading || isSchemaLoading

const binaryPlan = data?.binary_plan && JSON.parse(data.binary_plan)
const binaryPlanObj = useMemo(() => {
const json = data?.binary_plan_json ?? data?.binary_plan
if (json) {
return JSON.parse(json)
}
return undefined
}, [data?.binary_plan, data?.binary_plan_json])

const [isVpVisible, setIsVpVisable] = useState(false)
const toggleVisualPlan = (action: 'open' | 'close') => {
Expand Down Expand Up @@ -172,7 +178,7 @@ function PlanDetail({ query }: IPlanDetailProps) {
) : null}
</Descriptions>

{(binaryPlan || data.plan) && (
{(binaryPlanObj || data.plan) && (
<>
<Space size="middle" style={{ color: '#8c8c8c' }}>
{t('statement.pages.detail.desc.plans.execution.title')}
Expand Down Expand Up @@ -212,19 +218,19 @@ function PlanDetail({ query }: IPlanDetailProps) {
</Descriptions>
</Tabs.TabPane>

{binaryPlan && !binaryPlan.discardedDueToTooLong && (
{binaryPlanObj && !binaryPlanObj.discardedDueToTooLong && (
<Tabs.TabPane
tab={t(
'statement.pages.detail.desc.plans.execution.table'
)}
key="binary_plan_table"
>
<BinaryPlanTable data={binaryPlan} />
<BinaryPlanTable data={binaryPlanObj} />
<div style={{ height: 24 }} />
</Tabs.TabPane>
)}

{binaryPlan && !binaryPlan.main.discardedDueToTooLong && (
{binaryPlanObj && !binaryPlanObj.main.discardedDueToTooLong && (
<Tabs.TabPane
tab={t(
'statement.pages.detail.desc.plans.execution.visual'
Expand All @@ -244,12 +250,12 @@ function PlanDetail({ query }: IPlanDetailProps) {
height: window.innerHeight - 100
}}
>
<VisualPlanView data={binaryPlan} />
<VisualPlanView data={binaryPlanObj} />
</Modal>
<Descriptions>
<Descriptions.Item span={2}>
<div onClick={() => toggleVisualPlan('open')}>
<VisualPlanThumbnailView data={binaryPlan} />
<VisualPlanThumbnailView data={binaryPlanObj} />
</div>
</Descriptions.Item>
</Descriptions>
Expand Down
14 changes: 13 additions & 1 deletion ui/packages/tidb-dashboard-lib/src/client/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2177,7 +2177,13 @@ export interface SlowqueryModel {
*/
'binary_plan'?: string;
/**
*
* Computed fields
* @type {string}
* @memberof SlowqueryModel
*/
'binary_plan_json'?: string;
/**
* binary plan plain text
* @type {string}
* @memberof SlowqueryModel
*/
Expand Down Expand Up @@ -2934,6 +2940,12 @@ export interface StatementModel {
* @memberof StatementModel
*/
'binary_plan'?: string;
/**
*
* @type {string}
* @memberof StatementModel
*/
'binary_plan_json'?: string;
/**
*
* @type {string}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ export const BinaryPlanTable: React.FC<BinaryPlanTableProps> = ({ data }) => {
// truncate the string if it's too long
// operation info may be super super long
const truncateLength = 1000
let truncatedStr = row.operatorInfo
let truncatedStr = row.operatorInfo ?? ''
if (truncatedStr.length > truncateLength) {
truncatedStr = row.operatorInfo.slice(0, truncateLength) + '...'
}
Expand Down

0 comments on commit 5ac762b

Please sign in to comment.