Improve querying item results

The join to retrieve the attachment count per item turned out to be
very expensive. And it is not used anymore for the result, only to
support fulltext search. It is now removed from the query. The
DISTINCT keyword is also removed, because it is not necessary and it
is expensive. With the DISTINCT removed, a new index (provided in the
previous commit) can now be used to avoid sorting items.
This commit is contained in:
eikek 2021-08-29 00:21:49 +02:00
parent a5a8c2553b
commit 733096f979
3 changed files with 24 additions and 32 deletions

View File

@ -291,10 +291,13 @@ object OFulltext {
for { for {
items <- sqlResult items <- sqlResult
ids = items.map(a => ItemId[A].itemId(a)) ids = items.map(a => ItemId[A].itemId(a))
idsNel = NonEmptyList.fromFoldable(ids)
// must find all index results involving the items. // must find all index results involving the items.
// Currently there is one result per item + one result per // Currently there is one result per item + one result per
// attachment // attachment
limit = items.map(a => ItemId[A].fileCount(a)).sum + items.size limit <- idsNel
.map(itemIds => store.transact(QItem.countAttachmentsAndItems(itemIds)))
.getOrElse(0.pure[F])
ftsQ = fq.copy(items = ids.toSet, limit = limit) ftsQ = fq.copy(items = ids.toSet, limit = limit)
ftsR <- fts.search(ftsQ) ftsR <- fts.search(ftsQ)
ftsItems = ftsR.results.groupBy(_.itemId) ftsItems = ftsR.results.groupBy(_.itemId)
@ -320,22 +323,19 @@ object OFulltext {
trait ItemId[A] { trait ItemId[A] {
def itemId(a: A): Ident def itemId(a: A): Ident
def fileCount(a: A): Int
} }
object ItemId { object ItemId {
def apply[A](implicit ev: ItemId[A]): ItemId[A] = ev def apply[A](implicit ev: ItemId[A]): ItemId[A] = ev
def from[A](f: A => Ident, g: A => Int): ItemId[A] = def from[A](f: A => Ident): ItemId[A] =
new ItemId[A] { new ItemId[A] {
def itemId(a: A) = f(a) def itemId(a: A) = f(a)
def fileCount(a: A) = g(a)
} }
implicit val listItemId: ItemId[ListItem] = implicit val listItemId: ItemId[ListItem] =
ItemId.from(_.id, _.fileCount) ItemId.from(_.id)
implicit val listItemWithTagsId: ItemId[ListItemWithTags] = implicit val listItemWithTagsId: ItemId[ListItemWithTags] =
ItemId.from(_.item.id, _.item.fileCount) ItemId.from(_.item.id)
} }
} }

View File

@ -17,7 +17,6 @@ case class ListItem(
source: String, source: String,
direction: Direction, direction: Direction,
created: Timestamp, created: Timestamp,
fileCount: Int,
corrOrg: Option[IdRef], corrOrg: Option[IdRef],
corrPerson: Option[IdRef], corrPerson: Option[IdRef],
concPerson: Option[IdRef], concPerson: Option[IdRef],

View File

@ -43,6 +43,12 @@ object QItem {
private val tag = RTag.as("t") private val tag = RTag.as("t")
private val ti = RTagItem.as("ti") private val ti = RTagItem.as("ti")
def countAttachmentsAndItems(items: Nel[Ident]): ConnectionIO[Int] =
Select(count(a.id).s, from(a), a.itemId.in(items)).build
.query[Int]
.unique
.map(_ + items.size)
def findItem(id: Ident): ConnectionIO[Option[ItemData]] = { def findItem(id: Ident): ConnectionIO[Option[ItemData]] = {
val ref = RItem.as("ref") val ref = RItem.as("ref")
val cq = val cq =
@ -105,7 +111,6 @@ object QItem {
).build.query[ItemFieldValue].to[Vector] ).build.query[ItemFieldValue].to[Vector]
private def findItemsBase(q: Query.Fix, today: LocalDate, noteMaxLen: Int): Select = { private def findItemsBase(q: Query.Fix, today: LocalDate, noteMaxLen: Int): Select = {
val attachs = AttachCountTable("cta")
val coll = q.account.collective val coll = q.account.collective
Select( Select(
@ -118,7 +123,6 @@ object QItem {
i.source.s, i.source.s,
i.incoming.s, i.incoming.s,
i.created.s, i.created.s,
coalesce(attachs.num.s, const(0)).s,
org.oid.s, org.oid.s,
org.name.s, org.name.s,
pers0.pid.s, pers0.pid.s,
@ -136,17 +140,6 @@ object QItem {
), ),
from(i) from(i)
.leftJoin(f, f.id === i.folder && f.collective === coll) .leftJoin(f, f.id === i.folder && f.collective === coll)
.leftJoin(
Select(
select(countAll.as(attachs.num), a.itemId.as(attachs.itemId)),
from(a)
.innerJoin(i, i.id === a.itemId),
i.cid === q.account.collective,
GroupBy(a.itemId)
),
attachs.aliasName,
attachs.itemId === i.id
)
.leftJoin(pers0, pers0.pid === i.corrPerson && pers0.cid === coll) .leftJoin(pers0, pers0.pid === i.corrPerson && pers0.cid === coll)
.leftJoin(org, org.oid === i.corrOrg && org.cid === coll) .leftJoin(org, org.oid === i.corrOrg && org.cid === coll)
.leftJoin(pers1, pers1.pid === i.concPerson && pers1.cid === coll) .leftJoin(pers1, pers1.pid === i.concPerson && pers1.cid === coll)
@ -158,7 +151,7 @@ object QItem {
i.folder.in(QFolder.findMemberFolderIds(q.account)) i.folder.in(QFolder.findMemberFolderIds(q.account))
) )
) )
).distinct.orderBy( ).orderBy(
q.orderAsc q.orderAsc
.map(of => OrderBy.asc(coalesce(of(i).s, i.created.s).s)) .map(of => OrderBy.asc(coalesce(of(i).s, i.created.s).s))
.getOrElse(OrderBy.desc(coalesce(i.itemDate.s, i.created.s).s)) .getOrElse(OrderBy.desc(coalesce(i.itemDate.s, i.created.s).s))
@ -234,7 +227,7 @@ object QItem {
val tagCloud = val tagCloud =
findItemsBase(q.fix, today, 0).unwrap findItemsBase(q.fix, today, 0).unwrap
.withSelect(select(tag.all).append(count(i.id).as("num"))) .withSelect(select(tag.all).append(countDistinct(i.id).as("num")))
.changeFrom(_.prepend(tagFrom)) .changeFrom(_.prepend(tagFrom))
.changeWhere(c => c && queryCondition(today, q.fix.account.collective, q.cond)) .changeWhere(c => c && queryCondition(today, q.fix.account.collective, q.cond))
.groupBy(tag.tid) .groupBy(tag.tid)
@ -339,7 +332,7 @@ object QItem {
object Tids extends TableDef { object Tids extends TableDef {
val tableName = "tids" val tableName = "tids"
val alias: Option[String] = Some("tw") val alias = Some("tw")
val itemId = Column[Ident]("item_id", this) val itemId = Column[Ident]("item_id", this)
val weight = Column[Double]("weight", this) val weight = Column[Double]("weight", this)
val all = Vector[Column[_]](itemId, weight) val all = Vector[Column[_]](itemId, weight)