[vtadmin] Aggregate schema sizes#7751
Conversation
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
… later) Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Changes are to make it behave more similarly to the old `GetSchema`, so that I could repurpose those tests. At this point, we can delete `GetSchema` and rename `GetSchemaForKeyspace` Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
doeg
left a comment
There was a problem hiding this comment.
This looks great to me!!! A handful of lil non-blocking comments. Thank you again because I know this was a ton of work.
So excited to use this on the front-end. 😈
go/vt/vtadmin/cluster/cluster.go
Outdated
| BaseRequest *vtctldatapb.GetSchemaRequest | ||
| // SizeOpts control whether the (*Cluster).GetSchema method performs | ||
| // cross-shard table size aggregation (via the AggregateSizes field), and | ||
| // the behavior of that size aggregation (via the IncludeNonServingShards |
There was a problem hiding this comment.
Could you help me understand the use cases for the two values of IncludeNonServingShards? (Thinking of vtadmin-web but maybe there are others!) An entirely non-blocking question, of course. :)
Like, maybe it's as simple as a checkbox in the UI, and operators will already know when they care about one vs the other....? And/or is the diff between the two values interesting to show? (Also, is true the best default value, you think?)
There was a problem hiding this comment.
I had the same question. Wondering if we need this right now and maybe it is not worth having part of the API at the moment. My initial intuition is that only aggregating serving shards, seems sufficient. What other use cases you had in mind?
There was a problem hiding this comment.
Going to tag @rafael just to consolidate the discussion on this thread, since it's in at least two places now.
I'm actually having trouble articulating why we would ever want this (maybe if we were mid-split and wanted to see what the true total size of provisioned storage was vs what the logical size is (because in a split you would be double-counting between a source and its destination shards), but beyond that I'm not sure).
I think, though, that if we are going to keep it, false is the right default here. Because it's probably confusing if you weren't explicitly opting in to the potential double-counting.
Buttttt like I just said, maybe we should remove it entirely and just always skip non-serving shards. I'm curious to hear what you both think!
There was a problem hiding this comment.
I'd be in favor of always skipping non serving shards for now. If we see an use case in the future, then we iterate and add it.
There was a problem hiding this comment.
Omitting it sounds good to me, especially since it'll simplify the front-end a lil bit too. :)
go/vt/vtadmin/cluster/cluster.go
Outdated
| span, ctx := trace.NewSpan(ctx, "Cluster.FindAllShardsInKeyspace") | ||
|
|
||
| AnnotateSpan(c, span) | ||
| span.Annotate("keyspace", keyspace) | ||
|
|
||
| resp, err := c.Vtctld.FindAllShardsInKeyspace(ctx, &vtctldatapb.FindAllShardsInKeyspaceRequest{ | ||
| Keyspace: keyspace, | ||
| }) | ||
|
|
||
| span.Finish() |
There was a problem hiding this comment.
Really minor + non-blocking point -- did you consider a (c *Cluster) FindAllShardsInKeyspace function? That might simplify this a tiny bit, especially with the annotations. (It took me 0.2 seconds to realize that in this case we don't want a defer span.Finish() call.) 😊
There was a problem hiding this comment.
yeah, that sounds good! (i didn't because i didn't want to write more tests :shamebell:)
go/vt/vtadmin/cluster/cluster.go
Outdated
| if len(keyspaceTablets) == 0 { | ||
| // consider how to include info about the tablets we looked at, but | ||
| // that's also potentially a very long list .... maybe we should | ||
| // just log it (yes, do that). |
There was a problem hiding this comment.
Should this be a formal TODO? Haha 🌻
There was a problem hiding this comment.
I uhh meant for this to be for my eyes only 😬
go/vt/vtadmin/cluster/cluster.go
Outdated
|
|
||
| if _, ok = tableSize.ByShard[tablet.Tablet.Shard]; ok { | ||
| // We managed to query for the same shard twice, that's ... | ||
| // weird. but do we care? maybe just log? idk! |
There was a problem hiding this comment.
lol I do truly love this comment, but it is somewhat out of character with the rest so I wanted to point it out just in case
There was a problem hiding this comment.
Maybe we should error? That seems like it shouldn't happen, so if it does happen we better investigate??
| // Instead of starting at false, we start with whatever the base request | ||
| // specified. If we have exactly one tablet to query (i.e. we're not | ||
| // doing multi-shard aggregation), it's possible the request was to | ||
| // literally just get the table sizes; we shouldn't assume. If we have | ||
| // more than one tablet to query, then we are doing size aggregation, | ||
| // and we'll flip this to true after spawning the first GetSchema rpc. | ||
| sizesOnly = opts.BaseRequest.TableSizesOnly |
There was a problem hiding this comment.
This makes a lot of sense + I appreciate you annotating it inline!
rafael
left a comment
There was a problem hiding this comment.
I did my initial pass! Let me know your thoughts.
go/vt/vtadmin/cluster/cluster.go
Outdated
| // (described above) to find one SERVING tablet for each shard in the | ||
| // keyspace. If IncludeNonServingShards is false, then we will skip any | ||
| // shards for which IsMasterServing is false. | ||
| SizeOpts *vtadminpb.GetSchemaTableSizeOptions |
There was a problem hiding this comment.
Names are always hard. SizeOpts is a bit opaque to me. Maybe TableSizeAggregationOpts ? That is too mouthful...
I think we should come up with a better name.
There was a problem hiding this comment.
How about just TableSizeOptions and have it mirror the type name? I think it's a reasonable tradeoff between clarity and verbosity. Let me know what you think!
go/vt/vtadmin/cluster/cluster.go
Outdated
| BaseRequest *vtctldatapb.GetSchemaRequest | ||
| // SizeOpts control whether the (*Cluster).GetSchema method performs | ||
| // cross-shard table size aggregation (via the AggregateSizes field), and | ||
| // the behavior of that size aggregation (via the IncludeNonServingShards |
There was a problem hiding this comment.
I had the same question. Wondering if we need this right now and maybe it is not worth having part of the API at the moment. My initial intuition is that only aggregating serving shards, seems sufficient. What other use cases you had in mind?
go/vt/vtadmin/cluster/cluster.go
Outdated
|
|
||
| if _, ok = tableSize.ByShard[tablet.Tablet.Shard]; ok { | ||
| // We managed to query for the same shard twice, that's ... | ||
| // weird. but do we care? maybe just log? idk! |
There was a problem hiding this comment.
Maybe we should error? That seems like it shouldn't happen, so if it does happen we better investigate??
go/vt/vtadmin/cluster/cluster.go
Outdated
| sizesOnly = opts.BaseRequest.TableSizesOnly | ||
| ) | ||
|
|
||
| for _, tablet := range tabletsToQuery { |
There was a problem hiding this comment.
Here similar to my other comment about throttling. I'm not too concern, because I think this should scale pretty well as it's rpc to different hosts. But it does makes a bit nervous that for large keyspaces we can be making too many of this in parallel.
Wondering if putting a guardrail where we say: we only do X amount of parallelism will be good to have in place early on.
There was a problem hiding this comment.
Yeah, I think when we do the "bound topo RPCs to max concurrency" there should be two limits: tablet RPC max concurrency, and topo RPC max concurrency (maybe others). Then each of those gets configured (per cluster, so larger clusters could in theory have higher limits) and we spawn a waitgroup/pool/etc with that value as the capacity.
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
Signed-off-by: Andrew Mason <amason@slack-corp.com>
| type FindAllShardsInKeyspaceOptions struct { | ||
| // SkipDial indicates that the cluster can assume the vtctldclient has | ||
| // already dialed up a connection to a vtctld. | ||
| SkipDial bool |
There was a problem hiding this comment.
I'm curious why SkipDial is exposed as an option given that all uses (so far) are true. Requiring the caller to dial a vtctld connection seems like a fair contract to me + it seems like it'd simplify the interface quite a bit. Let me know if I missed something though!
There was a problem hiding this comment.
I'm of two minds about requiring callers to know the details enough to call Dial (though, this option just does the same thing, only one thin layer removed).
I think long term what I want is for a cluster to be smart about the last time it dialed, and "just do the right thing", and the caller doesn't need to know or care. I'd like to leave this as-is for now and noodle on that some more.
Description
This PR enhances the Get/Find Schema(s) endpoints to aggregate row counts and data lengths (more broadly, "sizes") across tablets from all shards in a given keyspace, so that vtadmin can display them to the user.
To make this work, I refactored a lot (but not all) of the logic around orchestrating and making
GetSchemavtctld rpcs from the API layer to the Cluster layer, including the addition of acluster.GetSchemaOptionstype to control the behavior of these cluster-level methods, as well as to allow us to continue to prefetch tablets as an optimization. We use thatGetSchemaOptionstype to also plumb through the size-aggregation options. There's extensive inline documentation about how the different options in this type affect the behavior, so I won't repeat them here.I also pulled out our tablet filtering code to a public function as
vtadminproto.FilterTabletsand added some additional trace annotation helper functions.Related Issue(s)
Checklist
Deployment Notes
Impacted Areas in Vitess
Components that this PR will affect: