perf(server): improve people query performance (#32441)
perf(server): improve people query performance (#32405) fix(server): slow people query (cherry picked from commit 6b79a82800cb984a755b163bca0cf689b486ad9a) Co-authored-by: Zack Pollard <zack@futo.org>
This commit is contained in:
co-authored by
Zack Pollard
parent
3dcaa05cd7
commit
ea1bfcf248
@@ -239,9 +239,12 @@ from
|
||||
"person_group"
|
||||
inner join "person" as "owned" on "owned"."personGroupId" = "person_group"."id"
|
||||
and "owned"."ownerId" = $5
|
||||
inner join "asset_face" on "asset_face"."personGroupId" = "person_group"."id"
|
||||
and "asset_face"."deletedAt" is null
|
||||
and "asset_face"."isVisible" is true
|
||||
inner join (
|
||||
select
|
||||
"asset_face"."personGroupId",
|
||||
count("asset"."id") as "faceCount"
|
||||
from
|
||||
"asset_face"
|
||||
inner join "asset" on "asset"."id" = "asset_face"."assetId"
|
||||
and "asset"."visibility" = 'timeline'
|
||||
and "asset"."deletedAt" is null
|
||||
@@ -261,16 +264,27 @@ from
|
||||
)
|
||||
)
|
||||
where
|
||||
"owned"."isHidden" = $8
|
||||
and 1 = 1
|
||||
"asset_face"."personGroupId" = any (
|
||||
array(
|
||||
(
|
||||
select
|
||||
"person"."personGroupId"
|
||||
from
|
||||
"person"
|
||||
where
|
||||
"person"."ownerId" = $8
|
||||
)
|
||||
)
|
||||
)
|
||||
and "asset_face"."deletedAt" is null
|
||||
and "asset_face"."isVisible" is true
|
||||
group by
|
||||
"person_group"."id",
|
||||
"owned"."ownerId",
|
||||
"owned"."personGroupId"
|
||||
having
|
||||
"asset_face"."personGroupId"
|
||||
) as "faces" on "faces"."personGroupId" = "person_group"."id"
|
||||
where
|
||||
(
|
||||
"owned"."name" != $9
|
||||
or count("asset"."id") >= COALESCE(
|
||||
or "faces"."faceCount" >= COALESCE(
|
||||
(
|
||||
SELECT
|
||||
value -> 'people' ->> 'minimumFaces'
|
||||
@@ -283,17 +297,19 @@ having
|
||||
'3'
|
||||
)::int
|
||||
)
|
||||
and "owned"."isHidden" = $11
|
||||
and 1 = 1
|
||||
order by
|
||||
"owned"."isHidden" asc,
|
||||
"owned"."isFavorite" desc,
|
||||
NULLIF("owned"."name", '') is null asc,
|
||||
count("asset"."id") desc,
|
||||
"faces"."faceCount" desc,
|
||||
NULLIF("owned"."name", '') asc nulls last,
|
||||
"owned"."createdAt"
|
||||
limit
|
||||
$11
|
||||
offset
|
||||
$12
|
||||
offset
|
||||
$13
|
||||
|
||||
-- PersonRepository.getAllWithoutFaces
|
||||
select
|
||||
@@ -901,9 +917,12 @@ from
|
||||
"person_group"
|
||||
inner join "person" as "owned" on "owned"."personGroupId" = "person_group"."id"
|
||||
and "owned"."ownerId" = $2
|
||||
inner join "asset_face" on "asset_face"."personGroupId" = "person_group"."id"
|
||||
and "asset_face"."deletedAt" is null
|
||||
and "asset_face"."isVisible" is true
|
||||
inner join (
|
||||
select
|
||||
"asset_face"."personGroupId",
|
||||
count("asset"."id") as "faceCount"
|
||||
from
|
||||
"asset_face"
|
||||
inner join "asset" on "asset"."id" = "asset_face"."assetId"
|
||||
and "asset"."visibility" = 'timeline'
|
||||
and "asset"."deletedAt" is null
|
||||
@@ -923,27 +942,40 @@ from
|
||||
)
|
||||
)
|
||||
where
|
||||
1 = 1
|
||||
group by
|
||||
"person_group"."id",
|
||||
"owned"."ownerId",
|
||||
"owned"."personGroupId"
|
||||
having
|
||||
"asset_face"."personGroupId" = any (
|
||||
array(
|
||||
(
|
||||
"owned"."name" != $5
|
||||
or count("asset"."id") >= COALESCE(
|
||||
select
|
||||
"person"."personGroupId"
|
||||
from
|
||||
"person"
|
||||
where
|
||||
"person"."ownerId" = $5
|
||||
)
|
||||
)
|
||||
)
|
||||
and "asset_face"."deletedAt" is null
|
||||
and "asset_face"."isVisible" is true
|
||||
group by
|
||||
"asset_face"."personGroupId"
|
||||
) as "faces" on "faces"."personGroupId" = "person_group"."id"
|
||||
where
|
||||
(
|
||||
"owned"."name" != $6
|
||||
or "faces"."faceCount" >= COALESCE(
|
||||
(
|
||||
SELECT
|
||||
value -> 'people' ->> 'minimumFaces'
|
||||
FROM
|
||||
user_metadata
|
||||
WHERE
|
||||
"userId" = $6
|
||||
"userId" = $7
|
||||
AND key = 'preferences'
|
||||
),
|
||||
'3'
|
||||
)::int
|
||||
)
|
||||
and 1 = 1
|
||||
) as "people"
|
||||
|
||||
-- PersonRepository.createGroup
|
||||
|
||||
@@ -224,8 +224,6 @@ const asPerson = ({ ownedPerson, otherPeople, sharedBy, sharedWith }: PersonGrou
|
||||
sharedWith,
|
||||
});
|
||||
|
||||
const faceCount = (eb: ExpressionBuilder<DB, 'asset'>) => eb.fn.count('asset.id');
|
||||
|
||||
const withPerson = ({ viewingUserId }: WithPersonOptions) => {
|
||||
return (eb: ExpressionBuilder<DB, 'asset_face'>) =>
|
||||
jsonObjectFrom(
|
||||
@@ -448,25 +446,40 @@ export class PersonRepository {
|
||||
.innerJoin('person as owned', (join) =>
|
||||
join.onRef('owned.personGroupId', '=', 'person_group.id').on('owned.ownerId', '=', userId),
|
||||
)
|
||||
.innerJoin('asset_face', (join) =>
|
||||
join
|
||||
.onRef('asset_face.personGroupId', '=', 'person_group.id')
|
||||
.on('asset_face.deletedAt', 'is', null)
|
||||
.on('asset_face.isVisible', 'is', true),
|
||||
)
|
||||
.innerJoin(
|
||||
(eb) =>
|
||||
eb
|
||||
.selectFrom('asset_face')
|
||||
.innerJoin('asset', (join) =>
|
||||
join
|
||||
.onRef('asset.id', '=', 'asset_face.assetId')
|
||||
.on('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
||||
.on('asset.deletedAt', 'is', null)
|
||||
.on((eb) => eb.or([eb('asset.ownerId', '=', anyUuid([userId, ...partnerIds])), inSharedAlbum(eb, userId)])),
|
||||
.on((eb) =>
|
||||
eb.or([eb('asset.ownerId', '=', anyUuid([userId, ...partnerIds])), inSharedAlbum(eb, userId)]),
|
||||
),
|
||||
)
|
||||
.groupBy(['person_group.id', 'owned.ownerId', 'owned.personGroupId'])
|
||||
.having((eb) =>
|
||||
.select('asset_face.personGroupId')
|
||||
.select((eb) => eb.fn.count<number>('asset.id').as('faceCount'))
|
||||
// an array instead of a join or `in`, which the planner may turn into a scan of every face in the instance
|
||||
.where('asset_face.personGroupId', '=', (eb) => {
|
||||
const ownedGroupIds = eb
|
||||
.selectFrom('person')
|
||||
.select('person.personGroupId')
|
||||
.where('person.ownerId', '=', userId);
|
||||
return eb.fn.any(eb.fn<string[]>('array', [ownedGroupIds]));
|
||||
})
|
||||
.where('asset_face.deletedAt', 'is', null)
|
||||
.where('asset_face.isVisible', 'is', true)
|
||||
.groupBy('asset_face.personGroupId')
|
||||
.as('faces'),
|
||||
(join) => join.onRef('faces.personGroupId', '=', 'person_group.id'),
|
||||
)
|
||||
.where((eb) =>
|
||||
eb.or([
|
||||
eb('owned.name', '!=', ''),
|
||||
eb(
|
||||
faceCount,
|
||||
'faces.faceCount',
|
||||
'>=',
|
||||
sql<number>`COALESCE(
|
||||
(SELECT value -> 'people' ->> 'minimumFaces'
|
||||
@@ -509,7 +522,7 @@ export class PersonRepository {
|
||||
.$if(!options.closestFaceAssetId, (qb) =>
|
||||
qb
|
||||
.orderBy(sql`NULLIF("owned"."name", '') is null`, 'asc')
|
||||
.orderBy(faceCount, 'desc')
|
||||
.orderBy('faces.faceCount', 'desc')
|
||||
.orderBy(sql`NULLIF("owned"."name", '')`, (om) => om.asc().nullsLast())
|
||||
.orderBy('owned.createdAt'),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user