-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Add index and table metrics to vttablet #17570
base: main
Are you sure you want to change the base?
Conversation
* IndexBytes * IndexCardinality * TableClusteredIndexSize * TableRows Signed-off-by: Rafer Hazen <[email protected]>
Review ChecklistHello reviewers! 👋 Please follow this checklist when reviewing this Pull Request. General
Tests
Documentation
New flags
If a workflow is added or modified:
Backward compatibility
|
Signed-off-by: Rafer Hazen <[email protected]>
Signed-off-by: Rafer Hazen <[email protected]>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #17570 +/- ##
==========================================
- Coverage 67.71% 67.65% -0.06%
==========================================
Files 1584 1585 +1
Lines 254721 256592 +1871
==========================================
+ Hits 172473 173608 +1135
- Misses 82248 82984 +736 ☔ View full report in Codecov by Sentry. |
@@ -432,7 +444,7 @@ func (se *Engine) reload(ctx context.Context, includeStats bool) error { | |||
// We therefore don't want to query for table sizes in getTableData() | |||
includeStats = false | |||
|
|||
innodbResults, err := conn.Conn.Exec(ctx, innodbTableSizesQuery, maxTableCount, false) | |||
innodbResults, err := conn.Conn.Exec(ctx, innodbTableSizesQuery, maxTableCount*maxPartitionsPerTable, false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Increased this because even with our limit of 10k tables, it's possible that there are more partitions than that (and this query returns one row per partition).
@@ -404,6 +404,10 @@ func TestReloadView(t *testing.T) { | |||
db.AddQuery("SELECT TABLE_NAME, CREATE_TIME FROM _vt.`tables`", &sqltypes.Result{}) | |||
// adding query pattern for udfs | |||
db.AddQueryPattern("SELECT name.*", &sqltypes.Result{}) | |||
db.AddQuery("select table_name, partition_name from information_schema.partitions where table_schema = database() and partition_name is not null", &sqltypes.Result{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love that these queries have leaked out of the schema
package, but I can't think of better way to make this test pass (unless we want to make the query constants public). Interested if this causes anyone concern.
@@ -466,8 +478,12 @@ func (se *Engine) reload(ctx context.Context, includeStats bool) error { | |||
} | |||
} | |||
} | |||
if err := se.updateTableIndexMetrics(ctx, conn.Conn); err != nil { | |||
log.Errorf("Updating index/table statistics failed, error: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just logs instead of failing the method. I figure if updateTableIndexMetrics
fails it's better to continue on since the only impact is missing metrics.
Description
This adds the following metrics to vttablet's schema engine.
TableRows
(by table) - The estimated number of rows in the tableTableClusteredIndexSize
(by table) - The size of the clustered index (i.e. the size of the "row data")IndexCardinality
(by index) - The estimated number of unique values in the indexIndexBytes
(by index) - The size of the indexmetrics sample
These values are read from mysql system tables when
Engine#Reload
is called, and made available viaEnv#Exporter
Partition names
Since mysql implements partitions internally as one table per partition, the "table name" referenced in the stats tables mostly look like
TABLE_NAME#p#PARTITION_NAME
. We want to report statistics per logical table (not per partition) so we need a way to extract the underlying table name. Unfortunately, it's not as simple as splitting the composite name by#p#
, because it's possible to create a table or partition with#p#
as a part of the name.The approach I took here is to load the
information_schema.partitions
table, which includes separate columns for the table and partition name. Then, as we read through the stats tables that contain the composite name, if we encounter a#p#
, we attempt to find a matching table/partition in the loaded list, and, if it is present, we can find the base table name.An alternative method would be to make use of
information_schema.innodb_tables.name
column (like we do here), which provides the table name with special characters encoded. This makes it possible to confidently split on#p#
, because the#
characters would be encoded if they were part of the real table or partition name. I opted for the "loading all partitions" approach instead because the joins required to get an encoded table name made the queries too slow when there are many tables, indexes or partitions.Performance
Since performance of the queries run on
#Reload
has been an issue in the past, I tested the queries added in this PR with the following test setup.Results:
updateTableIndexMetrics
method:716ms
37ms
15ms
205ms
427ms
For comparison the
InnoDBTableSizes
query takes2.0s
for the same test setup.Related Issue(s)
#17569
Checklist
Deployment Notes
None