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

sql: make InternalExecutor have the same descs.Collection as the parent #69495

Closed
rafiss opened this issue Aug 27, 2021 · 12 comments · Fixed by #82477
Closed

sql: make InternalExecutor have the same descs.Collection as the parent #69495

rafiss opened this issue Aug 27, 2021 · 12 comments · Fixed by #82477
Assignees
Labels
A-schema-descriptors Relating to SQL table/db descriptor handling. A-tools-activerecord A-tools-django A-tools-hasura A-tools-prisma C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) C-performance Perf of queries or internals. Solution not expected to change functional behavior. T-sql-foundations SQL Foundations Team (formerly SQL Schema + SQL Sessions)

Comments

@rafiss
Copy link
Collaborator

rafiss commented Aug 27, 2021

Is your feature request related to a problem? Please describe.
The internal executor uses a different descriptor Collection than the parent conn_executor. We've seen this cause performance problems since some builtins are implemented using the internal executor. If the builtin is called once per each output row in a query, then the table descriptors need to be re-fetched for each invocation of the internal executor.

@ajwerner suggests that not using the same Collection might be a correctness problem. #58356 (comment)

Describe the solution you'd like
It would be nice if the internal executor could use the same Collection as the conn_executor it's used from.

Describe alternatives you've considered
Implement builtins without using the internal executor.

Additional context
This caused severe performance problems in #57924 and #65551. We still have a backlog item for addressing other similar issues (#66173)

This was discussed in Slack: https://cockroachlabs.slack.com/archives/C0168LW5THS/p1611947857055600

Jira issue: CRDB-9622

Epic CRDB-14492

@rafiss rafiss added C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) C-performance Perf of queries or internals. Solution not expected to change functional behavior. A-schema-descriptors Relating to SQL table/db descriptor handling. labels Aug 27, 2021
@ajwerner
Copy link
Contributor

ajwerner commented Aug 27, 2021

Doing something pragmatic here where we tightly couple the InternalExecutor to the connExecutor it hangs off would be good.

Today the InternalExecutor gets the session data from the parent connExecutor but not the other extraTxnState. It gets a little bit crazy (very crazy?) if we wanted to have all of the extraTxnState shared between the two, but it also feels sort of right. I don't have a clear vision of what could go wrong.

There's also the fact that we take this txn argument on these Internal functions. What should the contract be? If you pass in the txn corresponding to the outer connExecutor then you get the rest of the extraTxnState and if you don't then you don't?

I think what I'd prefer is that we remove the Txn from the InternalExecutor methods altogether and we build something to bind the txn to the InternalExecutor. That way we could have two separate InternalExecutors during the execution of a statement.

I think there's good reason to bring sanity to this layer but doing a good job here isn't trivial.

@ajwerner
Copy link
Contributor

At its core, I think the problem here is that the internal executor abstraction is sitting at the wrong layer. It's this free-floating thing that is sort of associated with a session and sort of not. We should bind the internal executor much more closely to the session and connection. It should not take a transaction but rather should be initialized with one.

We'll still need to be careful with concurrency and transaction usage, but that's not new. This feels like a relatively important thing to do sooner rather than later.

@RichardJCai
Copy link
Contributor

This is only with regards to the InternalExecutor used for builtins (aka on EvalContext) right?

I think my PR here might fix it.
#71246

@ajwerner
Copy link
Contributor

This is only with regards to the InternalExecutor used for builtins (aka on EvalContext) right?

I think my PR here might fix it. #71246

How does this fix it? The internal executor hanging off of the ExecConfig is no better.

@RichardJCai
Copy link
Contributor

This is only with regards to the InternalExecutor used for builtins (aka on EvalContext) right?
I think my PR here might fix it. #71246

How does this fix it? The internal executor hanging off of the ExecConfig is no better.

Nvm just realized we still init a new conn_executor at https://github.com/cockroachdb/cockroach/blob/master/pkg/sql/internal.go#L182 which is where the Collections is created.

We could make it so InternalExecutor overrides could take Collections as a short term solution. Although I don't think having to always override to use the IE is a good idea which is what's going on in #71246 to use the IE for any builtins.

@ajwerner
Copy link
Contributor

Although I don't think having to always override to use the IE is a good idea which is what's going on in #71246 to use the IE for any builtins.

I agree. I think we should increase the coupling between the internal executor and the conn executor in the common case. See #71246 (comment).

@rafiss
Copy link
Collaborator Author

rafiss commented Nov 4, 2021

I think this is affecting activerecord too cockroachdb/activerecord-cockroachdb-adapter#234

@otan
Copy link
Contributor

otan commented Nov 24, 2021

I gave this a go (this was intended to be a quick and dirty to see if passing the same descCollection through is enough): #73100

But end up with this when running this query - any ideas?:

panic: interface conversion: catalog.NameEntry is *lease.descriptorVersionState, not *descs.uncommittedDescriptor

goroutine 3447 [running]:
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*uncommittedDescriptors).getByName(0xc00132e8c0, 0x0, 0x0, {0xc0039c2076, 0x8})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/uncommitted_descriptors.go:219 +0x17b
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getByName(0xc00132e888, {0x9bbcb70, 0xc002334000}, 0xc0047be9a0, {0x0, 0x0}, {0x0, 0x0}, {0xc0039c2076, 0x9}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/descriptor.go:182 +0x219
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getDatabaseByName(0x8, {0x9bbcb70, 0xc002334000}, 0x9bbcb70, {0xc0039c2076, 0x9}, {0x0, 0x0, 0x0, 0x0, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/database.go:63 +0x85
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).GetImmutableDatabaseByName(...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/database.go:45
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getObjectByNameIgnoringRequiredAndType(0xc00132e888, {0x9bbcb70, 0xc002334000}, 0x0, {0xc0039c2076, 0x9}, {0x86be9da, 0xd}, {0x86be9e8, 0x13}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/object.go:157 +0x149
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getObjectByName(0x8, {0x9bbcb70, 0xc002334000}, 0x171464d8, {0xc0039c2076, 0x10}, {0x86be9da, 0x10}, {0x86be9e8, 0x13}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/object.go:64 +0x1b2
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).GetObjectDesc(0x0, {0x9bbcb70, 0xc002334000}, 0x40e9e9e, {0xc0039c2076, 0xc0010dc99b}, {0x86be9da, 0x0}, {0x86be9e8, 0x13}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/object.go:39 +0x9f
github.com/cockroachdb/cockroach/pkg/sql.(*planner).LookupObject(0x0, {0x9bbcb70, 0xc002334000}, {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x0, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/resolver.go:190 +0x439
github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver.ResolveExisting({0x9bbcb70, 0xc002334000}, 0xc004062040, {0x1718a2c0, 0xc00132ec28}, {{0x1, 0x0, 0x0, 0x0, 0x0, ...}, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver/resolver.go:404 +0x143
github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver.ResolveExistingObject({0x9bbcb70, 0xc002334000}, {0x9c40c00, 0xc00132ec28}, 0xc004062040, {{0x1, 0x0, 0x0, 0x0, 0x0, ...}, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver/resolver.go:193 +0x173
github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver.ResolveExistingTableObject({0x9bbcb70, 0xc002334000}, {0x9c40c00, 0xc00132ec28}, 0xc00132f438, {{0x1, 0x0, 0x0, 0x0, 0x0, ...}, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver/resolver.go:121 +0x15d
github.com/cockroachdb/cockroach/pkg/sql.(*optCatalog).ResolveDataSource(0xc00132f420, {0x9bbcb70, 0xc002334000}, {0x0, 0x0}, 0xc0015af258)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/opt_catalog.go:207 +0x20f
github.com/cockroachdb/cockroach/pkg/sql/opt.(*Metadata).CheckDependencies(0xc004653c20, {0x9bbcb70, 0xc002334000}, {0x9d26100, 0xc00132f420})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/opt/metadata.go:293 +0xf7
github.com/cockroachdb/cockroach/pkg/sql/opt/memo.(*Memo).IsStale(0xc004653c20, {0x9bbcb70, 0xc002334000}, 0xc00132ee98, {0x9d26100, 0xc00132f420})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/opt/memo/memo.go:322 +0x493
github.com/cockroachdb/cockroach/pkg/sql.(*planner).prepareUsingOptimizer(0xc00132ec28, {0x9bbcb70, 0xc002334000})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/plan_opt.go:100 +0x8af
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).populatePrepared(0xc00132ed90, {0x9bbcb70, 0xc002334000}, 0xc0015d01f8, {0xc0015d01f8, 0x3, 0xc0015af608}, 0xc00132ec28)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:287 +0x22c
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).prepare.func1({0x9bbcb70, 0xc002334000}, 0x23)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:220 +0x40a
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).prepare(0xc00132e600, {0x9bbcb70, 0xc002334000}, {{{0x9bebb78, 0xc00141f680}, {0x86be98c, 0x104}, 0x3, 0x2}, {0xc00185eb40, ...}, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:226 +0x2cd
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).addPreparedStmt(0xc00132e600, {0x9bbcb70, 0xc002334000}, {0x0, 0x0}, {{{0x9bebb78, 0xc00141f680}, {0x86be98c, 0x104}, 0x3, ...}, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:111 +0x110
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execPrepare(0xc00132e600, {0x9bbcb70, 0xc002334000}, {{0x0, 0x0}, {{0x9bebb78, 0xc00141f680}, {0x86be98c, 0x104}, 0x3, ...}, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:53 +0x23b
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execCmd(0xc00132e600, {0x9bbcac8, 0xc003f61f40})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:1840 +0x11a6
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).run(0xc00132e600, {0x9bd8b38, 0xc003f5ef50}, 0xc002642fd0, {0x467fbd8, 0xc0004a0000, 0x0}, 0xc001950000)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:1672 +0x285
github.com/cockroachdb/cockroach/pkg/sql.(*InternalExecutor).initConnEx.func1()
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/internal.go:213 +0x8d
created by github.com/cockroachdb/cockroach/pkg/sql.(*InternalExecutor).initConnEx
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/internal.go:212 +0x5d4

@rafiss
Copy link
Collaborator Author

rafiss commented Nov 24, 2021

Curious if @RichardJCai has an idea? He did something similar in #71246

@RichardJCai
Copy link
Contributor

I gave this a go (this was intended to be a quick and dirty to see if passing the same descCollection through is enough): #73100

But end up with this when running this query - any ideas?:

panic: interface conversion: catalog.NameEntry is *lease.descriptorVersionState, not *descs.uncommittedDescriptor

goroutine 3447 [running]:
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*uncommittedDescriptors).getByName(0xc00132e8c0, 0x0, 0x0, {0xc0039c2076, 0x8})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/uncommitted_descriptors.go:219 +0x17b
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getByName(0xc00132e888, {0x9bbcb70, 0xc002334000}, 0xc0047be9a0, {0x0, 0x0}, {0x0, 0x0}, {0xc0039c2076, 0x9}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/descriptor.go:182 +0x219
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getDatabaseByName(0x8, {0x9bbcb70, 0xc002334000}, 0x9bbcb70, {0xc0039c2076, 0x9}, {0x0, 0x0, 0x0, 0x0, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/database.go:63 +0x85
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).GetImmutableDatabaseByName(...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/database.go:45
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getObjectByNameIgnoringRequiredAndType(0xc00132e888, {0x9bbcb70, 0xc002334000}, 0x0, {0xc0039c2076, 0x9}, {0x86be9da, 0xd}, {0x86be9e8, 0x13}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/object.go:157 +0x149
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).getObjectByName(0x8, {0x9bbcb70, 0xc002334000}, 0x171464d8, {0xc0039c2076, 0x10}, {0x86be9da, 0x10}, {0x86be9e8, 0x13}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/object.go:64 +0x1b2
github.com/cockroachdb/cockroach/pkg/sql/catalog/descs.(*Collection).GetObjectDesc(0x0, {0x9bbcb70, 0xc002334000}, 0x40e9e9e, {0xc0039c2076, 0xc0010dc99b}, {0x86be9da, 0x0}, {0x86be9e8, 0x13}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/descs/object.go:39 +0x9f
github.com/cockroachdb/cockroach/pkg/sql.(*planner).LookupObject(0x0, {0x9bbcb70, 0xc002334000}, {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, 0x0, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/resolver.go:190 +0x439
github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver.ResolveExisting({0x9bbcb70, 0xc002334000}, 0xc004062040, {0x1718a2c0, 0xc00132ec28}, {{0x1, 0x0, 0x0, 0x0, 0x0, ...}, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver/resolver.go:404 +0x143
github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver.ResolveExistingObject({0x9bbcb70, 0xc002334000}, {0x9c40c00, 0xc00132ec28}, 0xc004062040, {{0x1, 0x0, 0x0, 0x0, 0x0, ...}, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver/resolver.go:193 +0x173
github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver.ResolveExistingTableObject({0x9bbcb70, 0xc002334000}, {0x9c40c00, 0xc00132ec28}, 0xc00132f438, {{0x1, 0x0, 0x0, 0x0, 0x0, ...}, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver/resolver.go:121 +0x15d
github.com/cockroachdb/cockroach/pkg/sql.(*optCatalog).ResolveDataSource(0xc00132f420, {0x9bbcb70, 0xc002334000}, {0x0, 0x0}, 0xc0015af258)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/opt_catalog.go:207 +0x20f
github.com/cockroachdb/cockroach/pkg/sql/opt.(*Metadata).CheckDependencies(0xc004653c20, {0x9bbcb70, 0xc002334000}, {0x9d26100, 0xc00132f420})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/opt/metadata.go:293 +0xf7
github.com/cockroachdb/cockroach/pkg/sql/opt/memo.(*Memo).IsStale(0xc004653c20, {0x9bbcb70, 0xc002334000}, 0xc00132ee98, {0x9d26100, 0xc00132f420})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/opt/memo/memo.go:322 +0x493
github.com/cockroachdb/cockroach/pkg/sql.(*planner).prepareUsingOptimizer(0xc00132ec28, {0x9bbcb70, 0xc002334000})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/plan_opt.go:100 +0x8af
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).populatePrepared(0xc00132ed90, {0x9bbcb70, 0xc002334000}, 0xc0015d01f8, {0xc0015d01f8, 0x3, 0xc0015af608}, 0xc00132ec28)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:287 +0x22c
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).prepare.func1({0x9bbcb70, 0xc002334000}, 0x23)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:220 +0x40a
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).prepare(0xc00132e600, {0x9bbcb70, 0xc002334000}, {{{0x9bebb78, 0xc00141f680}, {0x86be98c, 0x104}, 0x3, 0x2}, {0xc00185eb40, ...}, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:226 +0x2cd
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).addPreparedStmt(0xc00132e600, {0x9bbcb70, 0xc002334000}, {0x0, 0x0}, {{{0x9bebb78, 0xc00141f680}, {0x86be98c, 0x104}, 0x3, ...}, ...}, ...)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:111 +0x110
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execPrepare(0xc00132e600, {0x9bbcb70, 0xc002334000}, {{0x0, 0x0}, {{0x9bebb78, 0xc00141f680}, {0x86be98c, 0x104}, 0x3, ...}, ...})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor_prepare.go:53 +0x23b
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).execCmd(0xc00132e600, {0x9bbcac8, 0xc003f61f40})
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:1840 +0x11a6
github.com/cockroachdb/cockroach/pkg/sql.(*connExecutor).run(0xc00132e600, {0x9bd8b38, 0xc003f5ef50}, 0xc002642fd0, {0x467fbd8, 0xc0004a0000, 0x0}, 0xc001950000)
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/conn_executor.go:1672 +0x285
github.com/cockroachdb/cockroach/pkg/sql.(*InternalExecutor).initConnEx.func1()
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/internal.go:213 +0x8d
created by github.com/cockroachdb/cockroach/pkg/sql.(*InternalExecutor).initConnEx
	/Users/otan/go/src/github.com/cockroachdb/cockroach/pkg/sql/internal.go:212 +0x5d4

I think I actually had a working method to pass the descCollections through in an earlier version of #71246, I don't recall running into any of those errors. Once #71246 is merged I can add back that code (trying to limit the scope of that refactor).

@ajwerner
Copy link
Contributor

ajwerner commented Dec 8, 2021

Once #71246 is merged I can add back that code (trying to limit the scope of that refactor).

@RichardJCai has the time come?

@RichardJCai
Copy link
Contributor

Once #71246 is merged I can add back that code (trying to limit the scope of that refactor).

@RichardJCai has the time come?

Pretty busy as of recent, I have another refactor in the works that I think I can easily tag this desc.Collections work (injecting desc.Collections) as part of. #73293

Will probably be a flex friday thing though.

ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 6, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 6, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 14, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 19, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 20, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 22, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 22, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 24, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 26, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Jul 28, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath an outer txn. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None

Release note (<category, see below>): <what> <show> <why>
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 1, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 2, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 3, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 5, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 9, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 9, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 9, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
ZhouXing19 added a commit to ZhouXing19/cockroach that referenced this issue Aug 10, 2022
Currently, the internal executor always create its own descriptor collections,
txn state, job collection and etc. for its conn executor, even though it's run
underneath a "parent" query. These recreation can unneccesarily reduce the
query efficiency in some use cases, such as when an internal executor is
used under a planner context. In this case, the internal executor is expected
to inherit these info from the planner, rather than creating its own.

To make this rule more explicit, this commit adds a series of query functions
under `sql.planner`. Each of these functions wrap both the init of an internal
executor and the query execution. In this way, the internal executor always
stores the info inherited from the parent planner, and will pass it to its child
conn executor.

fixes cockroachdb#69495

Release note: None
craig bot pushed a commit that referenced this issue Aug 12, 2022
82477: sql: introduce new internal executor interfaces r=rafiss,ajwerner a=ZhouXing19

This PR aims to provide a set of safer interfaces for the internal executor, making it less easy to abuse.

Currently, each conn executor underneath the internal executor (we call it “child executor”) has its own set of information, such as descriptor collection, job collection, schema change jobs, etc, even when it’s run with a not-nil outer `kv.Txn`, or there're multiple SQL executions under the same `kv.Txn`.
This is not intuitive, since it violates a rather deep principle that a `descs.Collection` and a SQL txn have a 1:1 relationship. The code doesn’t enforce that, but it ought to. The more places that make it possible to decouple this, the more anxious we get.

Ideally, internal executor with a not-nil txn is either planner or `collectionFactory` oriented, so that the txn is always tightly coupled with the descriptor collection. We thus propose a set of new interfaces to ensure this coupling.

Currently, the usage of an internal executor query function (e.g. `InternalExecutor.ExecEx()`) falls into the following 3 categories:
1. The query is run under a planner context and with a not-nil kv.Txn from this planner.
2. The query is run without a kv.Txn. (e.g. InternalExecutor.ExecEx(..., nil /* txn */, stmt...)
3. The query is running with a not-nil kv.Txn but not under the planner context.

For usage 1, the descriptor collections, txn state, job collections, and session data from the parent planner are expected to be passed to the internal executor's child conn executor.
For usage 2 and 3, if multiple SQL statements are run under the same txn, these executions should share the descs.Collection, txn state machine, job collections and session data for their conn executors. 

To suit these 3 use cases, we proposed 3 interfaces for each of the query function:
(In the following we use `InternalExecutor.ExecEx` as the example)
- For case 1, refactor to use `func (p *planner) ExecExUpdated()`, where the internal executor is always initialized with `descs.Collection`, `TxnState` and etc. from the `sql.planner`. 
- For case 2, refactor to use `ieFactory.WithoutTxn()`, where the query is always run with a nil kv.Txn. 
- For case 3, refactor to use `CollectionFactory.TxnWithExecutor()`. In this function, the internal executor is generated and passed to the call back function to run the query.

We also tried refactoring some of the existing use cases to give an example of the new interface.

(Note that the ultimate goal of this improvement is to deprecate all the "free-hanging" `InternalExecutor` objects (such as `sql.ExecutorConfig.InternalExecutor`) and replace them with an `InternalExecutorFactory` field. `InternalExecutorFactory` is to initialize a REAL internal executor, but it cannot be used directly to run SQL statement queries.
Instead, we wrap the initialization of an internal executor inside each query function, i.e. init it only when you really need to run a query. In other words, the creation of an internal executor becomes closer to the query running.)

fixes #69495
fixes #78998

Release Note: None



Co-authored-by: Jane Xing <zhouxing@uchicago.edu>
@craig craig bot closed this as completed in 8b17f6a Aug 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-schema-descriptors Relating to SQL table/db descriptor handling. A-tools-activerecord A-tools-django A-tools-hasura A-tools-prisma C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) C-performance Perf of queries or internals. Solution not expected to change functional behavior. T-sql-foundations SQL Foundations Team (formerly SQL Schema + SQL Sessions)
Projects
None yet
6 participants