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

Interim performance optimization for large input arg types #2128

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
8 changes: 8 additions & 0 deletions .changeset/dry-doors-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@dataplan/pg": patch
"grafast": patch
"postgraphile": patch
---

Reduce planning cost of large input object trees by evaluating keys up front
(thanks to @adamni21).
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
%%{init: {'themeVariables': { 'fontSize': '12px'}}}%%
graph TD
classDef path fill:#eee,stroke:#000,color:#000
classDef plan fill:#fff,stroke-width:1px,color:#000
classDef itemplan fill:#fff,stroke-width:2px,color:#000
classDef unbatchedplan fill:#dff,stroke-width:1px,color:#000
classDef sideeffectplan fill:#fcc,stroke-width:2px,color:#000
classDef bucket fill:#f6f6f6,color:#000,stroke-width:2px,text-align:left


%% plan dependencies
PgSelect13[["PgSelect[13∈0] ➊<br />ᐸforumsᐳ"]]:::plan
Object16{{"Object[16∈0] ➊<br />ᐸ{pgSettings,withPgClient}ᐳ"}}:::plan
Access23{{"Access[23∈0] ➊<br />ᐸ0.some.featured.equalToᐳ"}}:::plan
Object16 & Access23 --> PgSelect13
Access14{{"Access[14∈0] ➊<br />ᐸ2.pgSettingsᐳ"}}:::plan
Access15{{"Access[15∈0] ➊<br />ᐸ2.withPgClientᐳ"}}:::plan
Access14 & Access15 --> Object16
__Value2["__Value[2∈0] ➊<br />ᐸcontextᐳ"]:::plan
__Value2 --> Access14
__Value2 --> Access15
__Value0["__Value[0∈0] ➊<br />ᐸvariableValuesᐳ"]:::plan
__Value0 --> Access23
__Value4["__Value[4∈0] ➊<br />ᐸrootValueᐳ"]:::plan
__Item29[/"__Item[29∈1]<br />ᐸ13ᐳ"\]:::itemplan
PgSelect13 ==> __Item29
PgSelectSingle30{{"PgSelectSingle[30∈1]<br />ᐸforumsᐳ"}}:::plan
__Item29 --> PgSelectSingle30
Access45{{"Access[45∈1] ➊<br />ᐸ0.featured.notEqualToᐳ"}}:::plan
__Value0 --> Access45
PgSelect41[["PgSelect[41∈2]<br />ᐸmessagesᐳ"]]:::plan
PgClassExpression40{{"PgClassExpression[40∈2]<br />ᐸ__forums__.”id”ᐳ"}}:::plan
PgClassExpression49{{"PgClassExpression[49∈2]<br />ᐸ__forums__...chived_at”ᐳ"}}:::plan
Object16 & PgClassExpression40 & Access45 & PgClassExpression49 --> PgSelect41
PgClassExpression31{{"PgClassExpression[31∈2]<br />ᐸ__forums__.”name”ᐳ"}}:::plan
PgSelectSingle30 --> PgClassExpression31
PgSelectSingle30 --> PgClassExpression40
PgSelectSingle30 --> PgClassExpression49
__Item50[/"__Item[50∈3]<br />ᐸ41ᐳ"\]:::itemplan
PgSelect41 ==> __Item50
PgSelectSingle51{{"PgSelectSingle[51∈3]<br />ᐸmessagesᐳ"}}:::plan
__Item50 --> PgSelectSingle51
PgClassExpression52{{"PgClassExpression[52∈4]<br />ᐸ__messages__.”body”ᐳ"}}:::plan
PgSelectSingle51 --> PgClassExpression52
PgClassExpression53{{"PgClassExpression[53∈4]<br />ᐸ__messages__.”featured”ᐳ"}}:::plan
PgSelectSingle51 --> PgClassExpression53

%% define steps

subgraph "Buckets for queries/conditions/complex-filter-via-partial-variables"
Bucket0("Bucket 0 (root)<br /><br />1: <br />ᐳ: 14, 15, 23, 16<br />2: PgSelect[13]"):::bucket
classDef bucket0 stroke:#696969
class Bucket0,__Value0,__Value2,__Value4,PgSelect13,Access14,Access15,Object16,Access23 bucket0
Bucket1("Bucket 1 (listItem)<br />Deps: 0, 16<br /><br />ROOT __Item{1}ᐸ13ᐳ[29]"):::bucket
classDef bucket1 stroke:#00bfff
class Bucket1,__Item29,PgSelectSingle30,Access45 bucket1
Bucket2("Bucket 2 (nullableBoundary)<br />Deps: 30, 16, 45<br /><br />ROOT PgSelectSingle{1}ᐸforumsᐳ[30]<br />1: <br />ᐳ: 31, 40, 49<br />2: PgSelect[41]"):::bucket
classDef bucket2 stroke:#7f007f
class Bucket2,PgClassExpression31,PgClassExpression40,PgSelect41,PgClassExpression49 bucket2
Bucket3("Bucket 3 (listItem)<br /><br />ROOT __Item{3}ᐸ41ᐳ[50]"):::bucket
classDef bucket3 stroke:#ffa500
class Bucket3,__Item50,PgSelectSingle51 bucket3
Bucket4("Bucket 4 (nullableBoundary)<br />Deps: 51<br /><br />ROOT PgSelectSingle{3}ᐸmessagesᐳ[51]"):::bucket
classDef bucket4 stroke:#0000ff
class Bucket4,PgClassExpression52,PgClassExpression53 bucket4
Bucket0 --> Bucket1
Bucket1 --> Bucket2
Bucket2 --> Bucket3
Bucket3 --> Bucket4
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
select __forums_result__.*
from (select 0 as idx, $1::"bool" as "id0") as __forums_identifiers__,
lateral (
select
__forums__."name" as "0",
__forums__."id" as "1",
to_char(__forums__."archived_at", 'YYYY-MM-DD"T"HH24:MI:SS.USTZH:TZM'::text) as "2",
__forums_identifiers__.idx as "3"
from app_public.forums as __forums__
where
(
__forums__.archived_at is null
) and (
exists(
select 1
from app_public.messages as __messages_filter__
where
(
__forums__."id" = __messages_filter__."forum_id"
) and (
__messages_filter__.featured = __forums_identifiers__."id0"
)
)
) and (
true /* authorization checks */
)
order by __forums__."id" asc
) as __forums_result__;

select __messages_result__.*
from (select 0 as idx, $1::"uuid" as "id0", $2::"bool" as "id1", $3::"timestamptz" as "id2") as __messages_identifiers__,
lateral (
select
__messages__."body" as "0",
__messages__."featured"::text as "1",
__messages_identifiers__.idx as "2"
from app_public.messages as __messages__
where
(
__messages__.featured <> __messages_identifiers__."id1"
) and (
(__messages__.archived_at is null) = (__messages_identifiers__."id2" is null)
) and (
__messages__."forum_id" = __messages_identifiers__."id0"
)
order by __messages__."id" asc
) as __messages_result__;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
forums: [
{
name: "Postgres",
messagesList: [
{
body: "Postgres = awesome -- Alice",
featured: false,
},
{
body: "Postgres = awesome -- Cecilia",
featured: false,
},
],
},
],
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
%%{init: {'themeVariables': { 'fontSize': '12px'}}}%%
graph TD
classDef path fill:#eee,stroke:#000,color:#000
classDef plan fill:#fff,stroke-width:1px,color:#000
classDef itemplan fill:#fff,stroke-width:2px,color:#000
classDef unbatchedplan fill:#dff,stroke-width:1px,color:#000
classDef sideeffectplan fill:#fcc,stroke-width:2px,color:#000
classDef bucket fill:#f6f6f6,color:#000,stroke-width:2px,text-align:left


%% plan dependencies
PgSelect13[["PgSelect[13∈0] ➊<br />ᐸforumsᐳ"]]:::plan
Object16{{"Object[16∈0] ➊<br />ᐸ{pgSettings,withPgClient}ᐳ"}}:::plan
Access23{{"Access[23∈0] ➊<br />ᐸ0.some.featured.equalToᐳ"}}:::plan
Access45{{"Access[45∈0] ➊<br />ᐸ0.featured.notEqualToᐳ"}}:::plan
Object16 & Access23 & Access45 --> PgSelect13
Access14{{"Access[14∈0] ➊<br />ᐸ2.pgSettingsᐳ"}}:::plan
Access15{{"Access[15∈0] ➊<br />ᐸ2.withPgClientᐳ"}}:::plan
Access14 & Access15 --> Object16
__Value2["__Value[2∈0] ➊<br />ᐸcontextᐳ"]:::plan
__Value2 --> Access14
__Value2 --> Access15
__Value0["__Value[0∈0] ➊<br />ᐸvariableValuesᐳ"]:::plan
__Value0 --> Access23
__Value0 --> Access45
__Value4["__Value[4∈0] ➊<br />ᐸrootValueᐳ"]:::plan
__Item29[/"__Item[29∈1]<br />ᐸ13ᐳ"\]:::itemplan
PgSelect13 ==> __Item29
PgSelectSingle30{{"PgSelectSingle[30∈1]<br />ᐸforumsᐳ"}}:::plan
__Item29 --> PgSelectSingle30
PgClassExpression31{{"PgClassExpression[31∈2]<br />ᐸ__forums__.”name”ᐳ"}}:::plan
PgSelectSingle30 --> PgClassExpression31
Access54{{"Access[54∈2]<br />ᐸ29.1ᐳ"}}:::plan
__Item29 --> Access54
__Item50[/"__Item[50∈3]<br />ᐸ54ᐳ"\]:::itemplan
Access54 ==> __Item50
PgSelectSingle51{{"PgSelectSingle[51∈3]<br />ᐸmessagesᐳ"}}:::plan
__Item50 --> PgSelectSingle51
PgClassExpression52{{"PgClassExpression[52∈4]<br />ᐸ__messages__.”body”ᐳ"}}:::plan
PgSelectSingle51 --> PgClassExpression52
PgClassExpression53{{"PgClassExpression[53∈4]<br />ᐸ__messages__.”featured”ᐳ"}}:::plan
PgSelectSingle51 --> PgClassExpression53

%% define steps

subgraph "Buckets for queries/conditions/complex-filter-via-partial-variables"
Bucket0("Bucket 0 (root)<br /><br />1: <br />ᐳ: 14, 15, 23, 45, 16<br />2: PgSelect[13]"):::bucket
classDef bucket0 stroke:#696969
class Bucket0,__Value0,__Value2,__Value4,PgSelect13,Access14,Access15,Object16,Access23,Access45 bucket0
Bucket1("Bucket 1 (listItem)<br /><br />ROOT __Item{1}ᐸ13ᐳ[29]"):::bucket
classDef bucket1 stroke:#00bfff
class Bucket1,__Item29,PgSelectSingle30 bucket1
Bucket2("Bucket 2 (nullableBoundary)<br />Deps: 30, 29<br /><br />ROOT PgSelectSingle{1}ᐸforumsᐳ[30]"):::bucket
classDef bucket2 stroke:#7f007f
class Bucket2,PgClassExpression31,Access54 bucket2
Bucket3("Bucket 3 (listItem)<br /><br />ROOT __Item{3}ᐸ54ᐳ[50]"):::bucket
classDef bucket3 stroke:#ffa500
class Bucket3,__Item50,PgSelectSingle51 bucket3
Bucket4("Bucket 4 (nullableBoundary)<br />Deps: 51<br /><br />ROOT PgSelectSingle{3}ᐸmessagesᐳ[51]"):::bucket
classDef bucket4 stroke:#0000ff
class Bucket4,PgClassExpression52,PgClassExpression53 bucket4
Bucket0 --> Bucket1
Bucket1 --> Bucket2
Bucket2 --> Bucket3
Bucket3 --> Bucket4
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
select __forums_result__.*
from (select 0 as idx, $1::"bool" as "id0", $2::"bool" as "id1") as __forums_identifiers__,
lateral (
select
__forums__."name" as "0",
(select json_agg(s) from (
select
__messages__."body" as "0",
__messages__."featured"::text as "1"
from app_public.messages as __messages__
where
(
__messages__.featured <> __forums_identifiers__."id1"
) and (
(__messages__.archived_at is null) = (__forums__."archived_at" is null)
) and (
__forums__."id"::"uuid" = __messages__."forum_id"
)
order by __messages__."id" asc
) s) as "1",
__forums_identifiers__.idx as "2"
from app_public.forums as __forums__
where
(
__forums__.archived_at is null
) and (
exists(
select 1
from app_public.messages as __messages_filter__
where
(
__forums__."id" = __messages_filter__."forum_id"
) and (
__messages_filter__.featured = __forums_identifiers__."id0"
)
)
) and (
true /* authorization checks */
)
order by __forums__."id" asc
) as __forums_result__;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## expect(errors).toBeFalsy()
## expect(data.forums).toHaveLength(1);
## expect(data.forums[0].messagesList).toHaveLength(2);
## expect(data.forums[0].messagesList[0].featured).toBe(false);
## expect(data.forums[0].messagesList[1].featured).toBe(false);
#> variableValues: {"some": { "featured": { "equalTo": true } }, "featured": { notEqualTo: true } }
# NOTE: This query should return the same data as `complex-filter.test.graphql`
query NonFeaturedMessagesInForumsWithFeaturedMessage(
$some: MessageFilter
$featured: BooleanFilter
$isArchived: BooleanFilter
) {
forums(filter: { messages: { some: $some } }) {
name
messagesList(filter: { featured: $featured, isArchived: $isArchived }) {
body
featured
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
%%{init: {'themeVariables': { 'fontSize': '12px'}}}%%
graph TD
classDef path fill:#eee,stroke:#000,color:#000
classDef plan fill:#fff,stroke-width:1px,color:#000
classDef itemplan fill:#fff,stroke-width:2px,color:#000
classDef unbatchedplan fill:#dff,stroke-width:1px,color:#000
classDef sideeffectplan fill:#fcc,stroke-width:2px,color:#000
classDef bucket fill:#f6f6f6,color:#000,stroke-width:2px,text-align:left


%% plan dependencies
PgSelect11[["PgSelect[11∈0] ➊<br />ᐸforumsᐳ"]]:::plan
Object14{{"Object[14∈0] ➊<br />ᐸ{pgSettings,withPgClient}ᐳ"}}:::plan
Access45{{"Access[45∈0] ➊<br />ᐸ0.forumFilter.messages.some.featured.equalToᐳ"}}:::plan
Object14 & Access45 --> PgSelect11
Access12{{"Access[12∈0] ➊<br />ᐸ2.pgSettingsᐳ"}}:::plan
Access13{{"Access[13∈0] ➊<br />ᐸ2.withPgClientᐳ"}}:::plan
Access12 & Access13 --> Object14
__Value2["__Value[2∈0] ➊<br />ᐸcontextᐳ"]:::plan
__Value2 --> Access12
__Value2 --> Access13
__Value0["__Value[0∈0] ➊<br />ᐸvariableValuesᐳ"]:::plan
__Value0 --> Access45
__Value4["__Value[4∈0] ➊<br />ᐸrootValueᐳ"]:::plan
__Item55[/"__Item[55∈1]<br />ᐸ11ᐳ"\]:::itemplan
PgSelect11 ==> __Item55
PgSelectSingle56{{"PgSelectSingle[56∈1]<br />ᐸforumsᐳ"}}:::plan
__Item55 --> PgSelectSingle56
Access74{{"Access[74∈1] ➊<br />ᐸ0.messagesFilter.featured.notEqualToᐳ"}}:::plan
__Value0 --> Access74
PgSelect64[["PgSelect[64∈2]<br />ᐸmessagesᐳ"]]:::plan
PgClassExpression63{{"PgClassExpression[63∈2]<br />ᐸ__forums__.”id”ᐳ"}}:::plan
PgClassExpression82{{"PgClassExpression[82∈2]<br />ᐸ__forums__...chived_at”ᐳ"}}:::plan
Object14 & PgClassExpression63 & Access74 & PgClassExpression82 --> PgSelect64
PgClassExpression57{{"PgClassExpression[57∈2]<br />ᐸ__forums__.”name”ᐳ"}}:::plan
PgSelectSingle56 --> PgClassExpression57
PgSelectSingle56 --> PgClassExpression63
PgSelectSingle56 --> PgClassExpression82
__Item83[/"__Item[83∈3]<br />ᐸ64ᐳ"\]:::itemplan
PgSelect64 ==> __Item83
PgSelectSingle84{{"PgSelectSingle[84∈3]<br />ᐸmessagesᐳ"}}:::plan
__Item83 --> PgSelectSingle84
PgClassExpression85{{"PgClassExpression[85∈4]<br />ᐸ__messages__.”body”ᐳ"}}:::plan
PgSelectSingle84 --> PgClassExpression85
PgClassExpression86{{"PgClassExpression[86∈4]<br />ᐸ__messages__.”featured”ᐳ"}}:::plan
PgSelectSingle84 --> PgClassExpression86

%% define steps

subgraph "Buckets for queries/conditions/complex-filter-via-variables"
Bucket0("Bucket 0 (root)<br /><br />1: <br />ᐳ: 12, 13, 45, 14<br />2: PgSelect[11]"):::bucket
classDef bucket0 stroke:#696969
class Bucket0,__Value0,__Value2,__Value4,PgSelect11,Access12,Access13,Object14,Access45 bucket0
Bucket1("Bucket 1 (listItem)<br />Deps: 0, 14<br /><br />ROOT __Item{1}ᐸ11ᐳ[55]"):::bucket
classDef bucket1 stroke:#00bfff
class Bucket1,__Item55,PgSelectSingle56,Access74 bucket1
Bucket2("Bucket 2 (nullableBoundary)<br />Deps: 56, 14, 74<br /><br />ROOT PgSelectSingle{1}ᐸforumsᐳ[56]<br />1: <br />ᐳ: 57, 63, 82<br />2: PgSelect[64]"):::bucket
classDef bucket2 stroke:#7f007f
class Bucket2,PgClassExpression57,PgClassExpression63,PgSelect64,PgClassExpression82 bucket2
Bucket3("Bucket 3 (listItem)<br /><br />ROOT __Item{3}ᐸ64ᐳ[83]"):::bucket
classDef bucket3 stroke:#ffa500
class Bucket3,__Item83,PgSelectSingle84 bucket3
Bucket4("Bucket 4 (nullableBoundary)<br />Deps: 84<br /><br />ROOT PgSelectSingle{3}ᐸmessagesᐳ[84]"):::bucket
classDef bucket4 stroke:#0000ff
class Bucket4,PgClassExpression85,PgClassExpression86 bucket4
Bucket0 --> Bucket1
Bucket1 --> Bucket2
Bucket2 --> Bucket3
Bucket3 --> Bucket4
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
select __forums_result__.*
from (select 0 as idx, $1::"bool" as "id0") as __forums_identifiers__,
lateral (
select
__forums__."name" as "0",
__forums__."id" as "1",
to_char(__forums__."archived_at", 'YYYY-MM-DD"T"HH24:MI:SS.USTZH:TZM'::text) as "2",
__forums_identifiers__.idx as "3"
from app_public.forums as __forums__
where
(
__forums__.archived_at is null
) and (
exists(
select 1
from app_public.messages as __messages_filter__
where
(
__forums__."id" = __messages_filter__."forum_id"
) and (
__messages_filter__.featured = __forums_identifiers__."id0"
)
)
) and (
true /* authorization checks */
)
order by __forums__."id" asc
) as __forums_result__;

select __messages_result__.*
from (select 0 as idx, $1::"uuid" as "id0", $2::"bool" as "id1", $3::"timestamptz" as "id2") as __messages_identifiers__,
lateral (
select
__messages__."body" as "0",
__messages__."featured"::text as "1",
__messages_identifiers__.idx as "2"
from app_public.messages as __messages__
where
(
__messages__.featured <> __messages_identifiers__."id1"
) and (
(__messages__.archived_at is null) = (__messages_identifiers__."id2" is null)
) and (
__messages__."forum_id" = __messages_identifiers__."id0"
)
order by __messages__."id" asc
) as __messages_result__;
Loading
Loading