mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2026-09-03 20:53:09 -05:00
Video SQL query optimization
Reduce number of rows to parse in NodeJS by generating the JSON directly in PostgreSQL
This commit is contained in:
@@ -283,7 +283,7 @@ async function prepare () {
|
||||
}
|
||||
|
||||
servers = await Promise.all([
|
||||
createSingleServer(1, config, { nodeArgs: [ '--inspect' ] }),
|
||||
createSingleServer(1, config, { nodeArgs: [ '--inspect=9230' ] }),
|
||||
createSingleServer(2, config),
|
||||
createSingleServer(3, config)
|
||||
])
|
||||
|
||||
@@ -45,9 +45,14 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
|
||||
)
|
||||
|
||||
this.addJoin(
|
||||
'LEFT OUTER JOIN "actorImage" AS "VideoChannel->Actor->Avatars" ' +
|
||||
'ON "VideoChannel->Actor"."id" = "VideoChannel->Actor->Avatars"."actorId" ' +
|
||||
`AND "VideoChannel->Actor->Avatars"."type" = ${ActorImageType.AVATAR}`
|
||||
`LEFT JOIN LATERAL (` +
|
||||
`SELECT json_agg(` +
|
||||
` jsonb_build_object(` +
|
||||
` ` + this.tables.getAvatarAttributes().map(attr => `'${attr}', "${attr}"`).join(', ') +
|
||||
` )` +
|
||||
`) AS "Avatars"` +
|
||||
` FROM "actorImage" WHERE "actorId" = "VideoChannel->Actor"."id" AND "type" = ${ActorImageType.AVATAR}` +
|
||||
`) AS "VideoChannel->Actor->AvatarsJSON" ON TRUE`
|
||||
)
|
||||
|
||||
this.attributes = {
|
||||
@@ -55,7 +60,7 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
|
||||
|
||||
...this.buildAttributesObject('VideoChannel', this.tables.getChannelAttributes()),
|
||||
...this.buildActorInclude('VideoChannel->Actor'),
|
||||
...this.buildAvatarInclude('VideoChannel->Actor->Avatars'),
|
||||
'"VideoChannel->Actor->AvatarsJSON"."Avatars"': '"VideoChannel.Actor.AvatarsJSON"',
|
||||
...this.buildServerInclude('VideoChannel->Actor->Server')
|
||||
}
|
||||
}
|
||||
@@ -72,9 +77,14 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
|
||||
)
|
||||
|
||||
this.addJoin(
|
||||
'LEFT OUTER JOIN "actorImage" AS "VideoChannel->Account->Actor->Avatars" ' +
|
||||
'ON "VideoChannel->Account->Actor"."id" = "VideoChannel->Account->Actor->Avatars"."actorId" ' +
|
||||
`AND "VideoChannel->Account->Actor->Avatars"."type" = ${ActorImageType.AVATAR}`
|
||||
`LEFT JOIN LATERAL (` +
|
||||
`SELECT json_agg(` +
|
||||
` jsonb_build_object(` +
|
||||
` ` + this.tables.getAvatarAttributes().map(attr => `'${attr}', "${attr}"`).join(', ') +
|
||||
` )` +
|
||||
`) AS "Avatars"` +
|
||||
` FROM "actorImage" WHERE "actorId" = "VideoChannel->Account->Actor"."id" AND "type" = ${ActorImageType.AVATAR}` +
|
||||
`) AS "VideoChannel->Account->Actor->AvatarsJSON" ON TRUE`
|
||||
)
|
||||
|
||||
this.attributes = {
|
||||
@@ -82,18 +92,26 @@ export class AbstractVideoQueryBuilder extends AbstractRunQuery {
|
||||
|
||||
...this.buildAttributesObject('VideoChannel->Account', this.tables.getAccountAttributes()),
|
||||
...this.buildActorInclude('VideoChannel->Account->Actor'),
|
||||
...this.buildAvatarInclude('VideoChannel->Account->Actor->Avatars'),
|
||||
'"VideoChannel->Account->Actor->AvatarsJSON"."Avatars"': '"VideoChannel.Account.Actor.AvatarsJSON"',
|
||||
...this.buildServerInclude('VideoChannel->Account->Actor->Server')
|
||||
}
|
||||
}
|
||||
|
||||
protected includeThumbnails () {
|
||||
this.addJoin('LEFT OUTER JOIN "thumbnail" AS "Thumbnails" ON "video"."id" = "Thumbnails"."videoId"')
|
||||
protected includeThumbnailsJSON () {
|
||||
this.addJoin(
|
||||
` LEFT JOIN LATERAL (` +
|
||||
` SELECT json_agg(` +
|
||||
` jsonb_build_object(` +
|
||||
` ` + this.tables.getThumbnailAttributes().map(attr => `'${attr}', "${attr}"`).join(', ') +
|
||||
` )` +
|
||||
` ) AS "thumbnails" FROM "thumbnail" WHERE "videoId" = "video"."id"` +
|
||||
`) AS "ThumbnailsJSON" ON TRUE`
|
||||
)
|
||||
|
||||
this.attributes = {
|
||||
...this.attributes,
|
||||
|
||||
...this.buildAttributesObject('Thumbnails', this.tables.getThumbnailAttributes())
|
||||
'"ThumbnailsJSON"."thumbnails"': '"ThumbnailsJSON"'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,28 +268,29 @@ export class VideoModelBuilder {
|
||||
}
|
||||
|
||||
private addActorAvatar (row: SQLRow, actorPrefix: string, actor: ActorModel) {
|
||||
const avatarPrefix = `${actorPrefix}.Avatars`
|
||||
const id = row[`${avatarPrefix}.id`]
|
||||
const key = `${row.id}${id}`
|
||||
|
||||
if (!id || this.actorImagesDone.has(key)) return
|
||||
|
||||
const attributes = this.grab(row, this.tables.getAvatarAttributes(), avatarPrefix)
|
||||
const avatarModel = new ActorImageModel(attributes, this.buildOpts)
|
||||
actor.Avatars.push(avatarModel)
|
||||
|
||||
const key = `${actorPrefix}${row.id}`
|
||||
if (this.actorImagesDone.has(key)) return
|
||||
this.actorImagesDone.add(key)
|
||||
|
||||
const avatars = row[`${actorPrefix}.AvatarsJSON`] as any || []
|
||||
for (const avatar of avatars) {
|
||||
const avatarModel = new ActorImageModel(avatar, this.buildOpts)
|
||||
actor.Avatars.push(avatarModel)
|
||||
}
|
||||
}
|
||||
|
||||
private addThumbnail (row: SQLRow, videoModel: VideoModel) {
|
||||
const id = row['Thumbnails.id']
|
||||
if (!id || this.thumbnailsDone.has(id)) return
|
||||
if (this.thumbnailsDone.has(videoModel.id)) return
|
||||
|
||||
const attributes = this.grab(row, this.tables.getThumbnailAttributes(), 'Thumbnails')
|
||||
const thumbnailModel = new ThumbnailModel(attributes, this.buildOpts)
|
||||
videoModel.Thumbnails.push(thumbnailModel)
|
||||
const thumbnails = row['ThumbnailsJSON'] as any || []
|
||||
|
||||
this.thumbnailsDone.add(id)
|
||||
for (const thumbnail of thumbnails) {
|
||||
const thumbnailModel = new ThumbnailModel(thumbnail, this.buildOpts)
|
||||
|
||||
videoModel.Thumbnails.push(thumbnailModel)
|
||||
}
|
||||
|
||||
this.thumbnailsDone.add(videoModel.id)
|
||||
}
|
||||
|
||||
private addWebVideoFile (row: SQLRow, videoModel: VideoModel) {
|
||||
|
||||
@@ -137,7 +137,7 @@ export class VideosModelGetQuerySubBuilder extends AbstractVideoQueryBuilder {
|
||||
}
|
||||
|
||||
if (thumbnailsInclude.has(options.type)) {
|
||||
this.includeThumbnails()
|
||||
this.includeThumbnailsJSON()
|
||||
}
|
||||
|
||||
if (blacklistedInclude.has(options.type)) {
|
||||
|
||||
@@ -85,7 +85,7 @@ export class VideosModelListQueryBuilder extends AbstractVideoQueryBuilder {
|
||||
|
||||
this.includeChannels()
|
||||
this.includeAccounts()
|
||||
this.includeThumbnails()
|
||||
this.includeThumbnailsJSON()
|
||||
|
||||
if (options.user) {
|
||||
this.includeUserHistory(options.user.id)
|
||||
|
||||
Reference in New Issue
Block a user