Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui,server: Table stats collection details added to Database pages #76168

Merged
merged 1 commit into from
Feb 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generated/http/full.md
Original file line number Diff line number Diff line change
Expand Up @@ -4603,6 +4603,7 @@ a table.
| zone_config_level | [ZoneConfigurationLevel](#cockroach.server.serverpb.TableDetailsResponse-cockroach.server.serverpb.ZoneConfigurationLevel) | | The level at which this object's zone configuration is set. | [reserved](#support-status) |
| descriptor_id | [int64](#cockroach.server.serverpb.TableDetailsResponse-int64) | | descriptor_id is an identifier used to uniquely identify this table. It can be used to find events pertaining to this table by filtering on the 'target_id' field of events. | [reserved](#support-status) |
| configure_zone_statement | [string](#cockroach.server.serverpb.TableDetailsResponse-string) | | configure_zone_statement is the output of "SHOW ZONE CONFIGURATION FOR TABLE" for this table. It is a SQL statement that would re-configure the table's current zone if executed. | [reserved](#support-status) |
| stats_last_created_at | [google.protobuf.Timestamp](#cockroach.server.serverpb.TableDetailsResponse-google.protobuf.Timestamp) | | stats_last_created_at is the time at which statistics were last created. | [reserved](#support-status) |



Expand Down
6 changes: 6 additions & 0 deletions docs/generated/swagger/spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,12 @@
"format": "int64",
"x-go-name": "RangeCount"
},
"stats_last_created_at": {
"description": "stats_last_created_at is the time at which statistics were last created.",
"type": "string",
"format": "date-time",
"x-go-name": "StatsLastCreatedAt"
},
"zone_config": {
"$ref": "#/definitions/ZoneConfig"
},
Expand Down
2 changes: 2 additions & 0 deletions pkg/gen/excluded.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ EXCLUDED_SRCS = [
"//pkg/ui/workspaces/cluster-ui:dist/types/sessions/sessionsTableContent.d.ts",
"//pkg/ui/workspaces/cluster-ui:dist/types/sessions/terminateQueryModal.d.ts",
"//pkg/ui/workspaces/cluster-ui:dist/types/sessions/terminateSessionModal.d.ts",
"//pkg/ui/workspaces/cluster-ui:dist/types/settings/booleanSetting.d.ts",
"//pkg/ui/workspaces/cluster-ui:dist/types/settings/index.d.ts",
"//pkg/ui/workspaces/cluster-ui:dist/types/sortedtable/index.d.ts",
"//pkg/ui/workspaces/cluster-ui:dist/types/sortedtable/sortedtable.d.ts",
"//pkg/ui/workspaces/cluster-ui:dist/types/sortedtable/tableHead/index.d.ts",
Expand Down
19 changes: 19 additions & 0 deletions pkg/server/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,25 @@ func (s *adminServer) tableDetailsHelper(
resp.CreateTableStatement = createStmt
}

// Marshal SHOW STATISTICS result.
row, cols, err = s.server.sqlServer.internalExecutor.QueryRowExWithCols(
ctx, "admin-show-statistics", nil, /* txn */
sessiondata.InternalExecutorOverride{User: userName},
fmt.Sprintf("SELECT max(created) AS created FROM [SHOW STATISTICS FOR TABLE %s]", escQualTable),
)
if err != nil {
return nil, err
}
if row != nil {
scanner := makeResultScanner(cols)
const createdCol = "created"
var createdTs *time.Time
if err := scanner.Scan(row, createdCol, &createdTs); err != nil {
return nil, err
}
resp.StatsLastCreatedAt = createdTs
}

// Marshal SHOW ZONE CONFIGURATION result.
row, cols, err = s.server.sqlServer.internalExecutor.QueryRowExWithCols(
ctx, "admin-show-zone-config", nil, /* txn */
Expand Down
17 changes: 17 additions & 0 deletions pkg/server/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,7 @@ func TestAdminAPITableDetails(t *testing.T) {
"CREATE USER app",
fmt.Sprintf("GRANT SELECT ON %s.%s TO readonly", escDBName, tblName),
fmt.Sprintf("GRANT SELECT,UPDATE,DELETE ON %s.%s TO app", escDBName, tblName),
fmt.Sprintf("CREATE STATISTICS test_stats FROM %s.%s", escDBName, tblName),
}
pgURL, cleanupGoDB := sqlutils.PGUrl(
t, s.ServingSQLAddr(), "StartServer" /* prefix */, url.User(security.RootUser))
Expand Down Expand Up @@ -779,6 +780,22 @@ func TestAdminAPITableDetails(t *testing.T) {
}
}

// Verify statistics last updated.
{

showStatisticsForTableQuery := fmt.Sprintf("SELECT max(created) AS created FROM [SHOW STATISTICS FOR TABLE %s.%s]", escDBName, tblName)

row := db.QueryRow(showStatisticsForTableQuery)
var createdTs time.Time
if err := row.Scan(&createdTs); err != nil {
t.Fatal(err)
}

if a, e := resp.StatsLastCreatedAt, createdTs; reflect.DeepEqual(a, e) {
t.Fatalf("mismatched statistics creation timestamp; expected %s, got %s", e, a)
}
}

// Verify Descriptor ID.
tableID, err := ts.admin.queryTableID(ctx, security.RootUserName(), tc.dbName, tc.tblName)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions pkg/server/serverpb/admin.proto
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ message TableDetailsResponse {
// for this table. It is a SQL statement that would re-configure the table's current
// zone if executed.
string configure_zone_statement = 9;
// stats_last_created_at is the time at which statistics were last created.
google.protobuf.Timestamp stats_last_created_at = 10 [(gogoproto.stdtime) = true];
}

// TableStatsRequest is a request for detailed, computationally expensive
Expand Down
1 change: 1 addition & 0 deletions pkg/ui/workspaces/cluster-ui/src/core/colors.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ $colors--functional-orange-5: #764205;
$colors--title: $colors--neutral-8;
$colors--primary-text: $colors--neutral-7;
$colors--secondary-text: $colors--neutral-6;
$colors--success: $colors--primary-green-3;
$colors--disabled: $colors--neutral-5;
$colors--link: $colors--primary-blue-3;
$colors--white: $colors--neutral-0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from "./databaseDetailsPage";

import * as H from "history";
import moment from "moment";
const history = H.createHashHistory();

const withLoadingIndicator: DatabaseDetailsPageProps = {
Expand Down Expand Up @@ -107,6 +108,7 @@ const withData: DatabaseDetailsPageProps = {
userCount: roles.length,
roles: roles,
grants: grants,
statsLastUpdated: moment("0001-01-01T00:00:00Z"),
},
showNodeRegionsColumn: true,
stats: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import {
baseHeadingClasses,
statisticsClasses,
} from "src/transactionsPage/transactionsPageClasses";
import { Moment } from "moment";
import { formatDate } from "antd/es/date-picker/utils";

const cx = classNames.bind(styles);
const sortableTableCx = classNames.bind(sortableTableStyles);
Expand Down Expand Up @@ -101,6 +103,7 @@ export interface DatabaseDetailsPageDataTableDetails {
userCount: number;
roles: string[];
grants: string[];
statsLastUpdated?: Moment;
}

export interface DatabaseDetailsPageDataTableStats {
Expand Down Expand Up @@ -351,6 +354,26 @@ export class DatabaseDetailsPage extends React.Component<
showByDefault: this.props.showNodeRegionsColumn,
hideIfTenant: true,
},
{
title: (
<Tooltip
placement="bottom"
title="The last time table statistics were created or updated."
>
Table Stats Last Updated (UTC)
</Tooltip>
),
cell: table =>
!table.details.statsLastUpdated
? "No table statistics found"
: formatDate(
table.details.statsLastUpdated,
"MMM DD, YYYY [at] h:mm A",
),
sort: table => table.details.statsLastUpdated,
className: cx("database-table__col--table-stats"),
name: "tableStatsUpdated",
},
];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ const history = H.createHashHistory();
const withLoadingIndicator: DatabaseTablePageProps = {
databaseName: randomName(),
name: randomName(),
automaticStatsCollectionEnabled: true,
details: {
loading: true,
loaded: false,
createStatement: "",
replicaCount: 0,
indexNames: [],
grants: [],
statsLastUpdated: moment("0001-01-01T00:00:00Z"),
},
stats: {
loading: true,
Expand All @@ -58,13 +60,15 @@ const withLoadingIndicator: DatabaseTablePageProps = {
refreshTableStats: () => {},
refreshIndexStats: () => {},
resetIndexUsageStats: () => {},
refreshSettings: () => {},
};

const name = randomName();

const withData: DatabaseTablePageProps = {
databaseName: randomName(),
name: name,
automaticStatsCollectionEnabled: true,
details: {
loading: false,
loaded: true,
Expand All @@ -89,6 +93,7 @@ const withData: DatabaseTablePageProps = {
};
}),
),
statsLastUpdated: moment("0001-01-01T00:00:00Z"),
},
showNodeRegionsSection: true,
stats: {
Expand Down Expand Up @@ -136,6 +141,7 @@ const withData: DatabaseTablePageProps = {
refreshTableStats: () => {},
refreshIndexStats: () => {},
resetIndexUsageStats: () => {},
refreshSettings: () => {},
};

storiesOf("Database Table Page", module)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,19 @@ import _ from "lodash";
import { Tooltip } from "antd";
import { Heading } from "@cockroachlabs/ui-components";

import { Anchor } from "src/anchor";
import { Breadcrumbs } from "src/breadcrumbs";
import { CaretRight } from "src/icon/caretRight";
import { StackIcon } from "src/icon/stackIcon";
import { SqlBox } from "src/sql";
import { ColumnDescriptor, SortSetting, SortedTable } from "src/sortedtable";
import { SummaryCard, SummaryCardItem } from "src/summaryCard";
import {
SummaryCard,
SummaryCardItem,
SummaryCardItemBoolSetting,
} from "src/summaryCard";
import * as format from "src/util/format";
import { syncHistory } from "src/util";
import { syncHistory, tableStatsClusterSetting } from "src/util";

import styles from "./databaseTablePage.module.scss";
import { commonStyles } from "src/common";
Expand All @@ -32,7 +37,10 @@ import moment, { Moment } from "moment";
import { Search as IndexIcon } from "@cockroachlabs/icons";
import { formatDate } from "antd/es/date-picker/utils";
import { Link } from "react-router-dom";
import classnames from "classnames/bind";
import booleanSettingStyles from "../settings/booleanSetting.module.scss";
const cx = classNames.bind(styles);
const booleanSettingCx = classnames.bind(booleanSettingStyles);

const { TabPane } = Tabs;

Expand Down Expand Up @@ -84,6 +92,7 @@ export interface DatabaseTablePageData {
stats: DatabaseTablePageDataStats;
indexStats: DatabaseTablePageIndexStats;
showNodeRegionsSection?: boolean;
automaticStatsCollectionEnabled: boolean;
}

export interface DatabaseTablePageDataDetails {
Expand All @@ -93,6 +102,7 @@ export interface DatabaseTablePageDataDetails {
replicaCount: number;
indexNames: string[];
grants: Grant[];
statsLastUpdated?: Moment;
}

export interface DatabaseTablePageIndexStats {
Expand Down Expand Up @@ -125,6 +135,7 @@ export interface DatabaseTablePageDataStats {
export interface DatabaseTablePageActions {
refreshTableDetails: (database: string, table: string) => void;
refreshTableStats: (database: string, table: string) => void;
refreshSettings: () => void;
refreshIndexStats?: (database: string, table: string) => void;
resetIndexUsageStats?: (database: string, table: string) => void;
refreshNodes?: () => void;
Expand Down Expand Up @@ -203,6 +214,10 @@ export class DatabaseTablePage extends React.Component<
this.props.name,
);
}

if (this.props.refreshSettings != null) {
this.props.refreshSettings();
}
}

minDate = moment.utc("0001-01-01"); // minimum value as per UTC
Expand Down Expand Up @@ -359,6 +374,36 @@ export class DatabaseTablePage extends React.Component<
label="Ranges"
value={this.props.stats.rangeCount}
/>
{this.props.details.statsLastUpdated && (
<SummaryCardItem
label="Table Stats Last Updated"
value={formatDate(
this.props.details.statsLastUpdated,
"MMM DD, YYYY [at] h:mm A [(UTC)]",
)}
/>
)}
<SummaryCardItemBoolSetting
label="Auto Stats Collection"
value={this.props.automaticStatsCollectionEnabled}
toolTipText={
<span>
{" "}
Automatic statistics can help improve query
performance. Learn how to{" "}
<Anchor
href={tableStatsClusterSetting}
target="_blank"
className={booleanSettingCx(
"crl-hover-text__link-text",
)}
>
manage statistics collection
</Anchor>
.
</span>
}
/>
</SummaryCard>
</Col>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ const history = H.createHashHistory();
const withLoadingIndicator: DatabasesPageProps = {
loading: true,
loaded: false,
automaticStatsCollectionEnabled: true,
databases: [],
sortSetting: {
ascending: false,
columnTitle: "name",
},
onSortingChange: () => {},
refreshDatabases: () => {},
refreshSettings: () => {},
refreshDatabaseDetails: () => {},
refreshTableStats: () => {},
location: history.location,
Expand All @@ -44,13 +46,15 @@ const withLoadingIndicator: DatabasesPageProps = {
const withoutData: DatabasesPageProps = {
loading: false,
loaded: true,
automaticStatsCollectionEnabled: true,
databases: [],
sortSetting: {
ascending: false,
columnTitle: "name",
},
onSortingChange: () => {},
refreshDatabases: () => {},
refreshSettings: () => {},
refreshDatabaseDetails: () => {},
refreshTableStats: () => {},
location: history.location,
Expand All @@ -67,6 +71,7 @@ const withData: DatabasesPageProps = {
loading: false,
loaded: true,
showNodeRegionsColumn: true,
automaticStatsCollectionEnabled: true,
sortSetting: {
ascending: false,
columnTitle: "name",
Expand All @@ -86,6 +91,7 @@ const withData: DatabasesPageProps = {
}),
onSortingChange: () => {},
refreshDatabases: () => {},
refreshSettings: () => {},
refreshDatabaseDetails: () => {},
refreshTableStats: () => {},
location: history.location,
Expand Down
Loading