summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2024-10-23 00:31:53 -0400
committerOwen Jacobson <owen@grimoire.ca>2024-10-23 00:42:00 -0400
commit3fab58827017041168a769184469cff3722d6c38 (patch)
tree043b49c36976a1eec8fe4306a1e88d3cc2a27e62 /src
parent6f7f4410980edd13c57ad54697ebe99d739fef76 (diff)
Make sure (most) queries avoid table scans.
I've exempted inserts (they never scan in the first place), queries on `event_sequence` (at most one row), and the coalesce()s used for event replay (for now; these are obviously a performance risk area and need addressing). Method: ``` find .sqlx -name 'query-*.json' -exec jq -r '"explain query plan " + .query + ";"' {} + > explain.sql ``` Then go query by query through the resulting file.
Diffstat (limited to 'src')
-rw-r--r--src/boot/app.rs2
-rw-r--r--src/channel/repo.rs14
-rw-r--r--src/login/repo.rs2
-rw-r--r--src/message/repo.rs16
4 files changed, 16 insertions, 18 deletions
diff --git a/src/boot/app.rs b/src/boot/app.rs
index 1d88608..e716b58 100644
--- a/src/boot/app.rs
+++ b/src/boot/app.rs
@@ -23,7 +23,7 @@ impl<'a> Boot<'a> {
let resume_point = tx.sequence().current().await?;
let logins = tx.logins().all(resume_point.into()).await?;
- let channels = tx.channels().all(resume_point.into()).await?;
+ let channels = tx.channels().all(resume_point).await?;
let messages = tx.messages().all(resume_point.into()).await?;
tx.commit().await?;
diff --git a/src/channel/repo.rs b/src/channel/repo.rs
index e26ac2b..a49db52 100644
--- a/src/channel/repo.rs
+++ b/src/channel/repo.rs
@@ -104,13 +104,13 @@ impl<'c> Channels<'c> {
Ok(channel)
}
- pub async fn all(&mut self, resume_at: ResumePoint) -> Result<Vec<History>, LoadError> {
+ pub async fn all(&mut self, resume_at: Sequence) -> Result<Vec<History>, LoadError> {
let channels = sqlx::query!(
r#"
select
id as "id: Id",
- name.display_name as "display_name: String",
- name.canonical_name as "canonical_name: String",
+ name.display_name as "display_name?: String",
+ name.canonical_name as "canonical_name?: String",
channel.created_at as "created_at: DateTime",
channel.created_sequence as "created_sequence: Sequence",
deleted.deleted_at as "deleted_at?: DateTime",
@@ -120,7 +120,7 @@ impl<'c> Channels<'c> {
using (id)
left join channel_deleted as deleted
using (id)
- where coalesce(channel.created_sequence <= $1, true)
+ where channel.created_sequence <= $1
order by name.canonical_name
"#,
resume_at,
@@ -144,7 +144,7 @@ impl<'c> Channels<'c> {
Ok(channels)
}
- pub async fn replay(&mut self, resume_at: Option<Sequence>) -> Result<Vec<History>, LoadError> {
+ pub async fn replay(&mut self, resume_at: ResumePoint) -> Result<Vec<History>, LoadError> {
let channels = sqlx::query!(
r#"
select
@@ -263,8 +263,8 @@ impl<'c> Channels<'c> {
r#"
select
channel.id as "id: Id",
- name.display_name as "display_name: String",
- name.canonical_name as "canonical_name: String",
+ name.display_name as "display_name?: String",
+ name.canonical_name as "canonical_name?: String",
channel.created_at as "created_at: DateTime",
channel.created_sequence as "created_sequence: Sequence",
deleted.deleted_at as "deleted_at?: DateTime",
diff --git a/src/login/repo.rs b/src/login/repo.rs
index c6bc734..611edd6 100644
--- a/src/login/repo.rs
+++ b/src/login/repo.rs
@@ -69,7 +69,7 @@ impl<'c> Logins<'c> {
created_at as "created_at: DateTime"
from login
where coalesce(created_sequence <= $1, true)
- order by created_sequence
+ order by canonical_name
"#,
resume_at,
)
diff --git a/src/message/repo.rs b/src/message/repo.rs
index 4cfefec..c8ceceb 100644
--- a/src/message/repo.rs
+++ b/src/message/repo.rs
@@ -79,8 +79,8 @@ impl<'c> Messages<'c> {
message.body as "body: Body",
message.sent_at as "sent_at: DateTime",
message.sent_sequence as "sent_sequence: Sequence",
- deleted.deleted_at as "deleted_at: DateTime",
- deleted.deleted_sequence as "deleted_sequence: Sequence"
+ deleted.deleted_at as "deleted_at?: DateTime",
+ deleted.deleted_sequence as "deleted_sequence?: Sequence"
from message
left join message_deleted as deleted
using (id)
@@ -186,33 +186,31 @@ impl<'c> Messages<'c> {
) -> Result<History, sqlx::Error> {
let id = message.id();
- sqlx::query_scalar!(
+ sqlx::query!(
r#"
insert into message_deleted (id, deleted_at, deleted_sequence)
values ($1, $2, $3)
- returning 1 as "deleted: bool"
"#,
id,
deleted.at,
deleted.sequence,
)
- .fetch_one(&mut *self.0)
+ .execute(&mut *self.0)
.await?;
// Small social responsibility hack here: when a message is deleted, its body is
// retconned to have been the empty string. Someone reading the event stream
// afterwards, or looking at messages in the channel, cannot retrieve the
// "deleted" message by ignoring the deletion event.
- sqlx::query_scalar!(
+ sqlx::query!(
r#"
update message
- set body = ""
+ set body = ''
where id = $1
- returning 1 as "blanked: bool"
"#,
id,
)
- .fetch_one(&mut *self.0)
+ .execute(&mut *self.0)
.await?;
let message = self.by_id(id).await?;