feat: optimize database indexes

This commit is contained in:
aslost
2026-08-25 12:22:56 +08:00
parent 1880d5080b
commit 5ea856bd30
3 changed files with 104 additions and 128 deletions
+18 -25
View File
@@ -31,36 +31,29 @@ const dbInit = {
await this.v3_0DB(c);
await this.v3_1DB(c);
await this.v3_2DB(c);
await this.v3_3DB(c);
await settingService.refresh(c);
return c.text('success');
},
async v3_3DB(c) {
const oauthSwitchFields = [
'linuxdo_switch', 'github_switch', 'google_switch',
];
for (const field of oauthSwitchFields) {
try {
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN ${field} INTEGER NOT NULL DEFAULT 1;`).run();
} catch (e) {
console.warn(`跳过字段:${e.message}`);
}
}
},
async v3_2DB(c) {
const oauthFields = [
'linuxdo_client_id', 'linuxdo_client_secret',
'github_client_id', 'github_client_secret',
'google_client_id', 'google_client_secret',
];
for (const field of oauthFields) {
try {
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN ${field} TEXT NOT NULL DEFAULT '';`).run();
} catch (e) {
console.warn(`跳过字段:${e.message}`);
}
try {
await c.env.db.batch([
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN linuxdo_client_id TEXT NOT NULL DEFAULT '';`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN linuxdo_client_secret TEXT NOT NULL DEFAULT '';`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN github_client_id TEXT NOT NULL DEFAULT '';`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN github_client_secret TEXT NOT NULL DEFAULT '';`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN google_client_id TEXT NOT NULL DEFAULT '';`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN google_client_secret TEXT NOT NULL DEFAULT '';`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN linuxdo_switch INTEGER NOT NULL DEFAULT 1;`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN github_switch INTEGER NOT NULL DEFAULT 1;`),
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN google_switch INTEGER NOT NULL DEFAULT 1;`),
await c.env.db.prepare(`CREATE INDEX IF NOT EXISTS idx_email_list_user ON email(user_id, type, is_del, email_id)`),
await c.env.db.prepare(`CREATE INDEX IF NOT EXISTS idx_email_list_account ON email(user_id, account_id, type, is_del, email_id)`),
await c.env.db.prepare(`CREATE INDEX IF NOT EXISTS idx_star_user_email ON star(user_id, email_id)`),
await c.env.db.prepare(`CREATE INDEX IF NOT EXISTS idx_star_email_user ON star(email_id, user_id)`)
]);
} catch (e) {
console.warn(`跳过字段:${e.message}`);
}
},
+84 -97
View File
@@ -30,7 +30,7 @@ const emailService = {
let { emailId, type, accountId, size, timeSort, allReceive } = params;
size = Number(size);
emailId = Number(emailId);
emailId = Number(emailId) || 0;
timeSort = Number(timeSort);
accountId = Number(accountId);
allReceive = Number(allReceive);
@@ -39,21 +39,14 @@ const emailService = {
size = 50;
}
if (!emailId) {
if (timeSort) {
emailId = 0;
} else {
emailId = 9999999999;
}
}
if (isNaN(allReceive)) {
let accountRow = await accountService.selectById(c, accountId);
allReceive = accountRow.allReceive;
}
const filters = this.emailListFilters({ userId, accountId, type, allReceive, emailId, timeSort });
const countFilters = this.emailListFilters({ userId, accountId, type, allReceive, withCursor: false });
const query = orm(c)
.select({
...email,
@@ -66,20 +59,12 @@ const emailService = {
eq(star.emailId, email.emailId),
eq(star.userId, userId)
)
).leftJoin(
)
.innerJoin(
account,
eq(account.accountId, email.accountId)
)
.where(
and(
allReceive ? eq(1,1) : eq(email.accountId, accountId),
eq(email.userId, userId),
timeSort ? gt(email.emailId, emailId) : lt(email.emailId, emailId),
eq(email.type, type),
eq(email.isDel, isDel.NORMAL),
eq(account.isDel, isDel.NORMAL)
)
);
.where(and(...filters));
if (timeSort) {
query.orderBy(asc(email.emailId));
@@ -90,26 +75,19 @@ const emailService = {
const listQuery = query.limit(size).all();
const totalQuery = orm(c).select({ total: count() }).from(email)
.leftJoin(
.innerJoin(
account,
eq(account.accountId, email.accountId)
)
.where(
and(
allReceive ? eq(1,1) : eq(email.accountId, accountId),
eq(email.userId, userId),
eq(email.type, type),
eq(email.isDel, isDel.NORMAL),
eq(account.isDel, isDel.NORMAL)
)
).get();
.where(and(...countFilters))
.get();
const latestEmailQuery = orm(c).select().from(email).where(
and(
allReceive ? eq(1,1) : eq(email.accountId, accountId),
eq(email.userId, userId),
eq(email.type, type),
eq(email.isDel, isDel.NORMAL)
eq(email.isDel, isDel.NORMAL),
allReceive ? undefined : eq(email.accountId, accountId)
))
.orderBy(desc(email.emailId)).limit(1).get();
@@ -134,6 +112,71 @@ const emailService = {
return { list, total: totalRow.total, latestEmail };
},
emailListFilters({ userId, accountId, type, allReceive, emailId, timeSort, withCursor = true }) {
const conditions = [
eq(email.userId, userId),
eq(email.type, type),
eq(email.isDel, isDel.NORMAL),
eq(account.isDel, isDel.NORMAL),
];
if (!allReceive) {
conditions.push(eq(email.accountId, accountId));
}
if (withCursor && emailId) {
conditions.push(timeSort ? gt(email.emailId, emailId) : lt(email.emailId, emailId));
}
return conditions;
},
allEmailListFilters({ emailId, name, subject, accountEmail, userEmail, type, timeSort, withCursor = true }) {
const conditions = [];
if (type === 'send') {
conditions.push(eq(email.type, emailConst.type.SEND));
}
if (type === 'receive') {
conditions.push(eq(email.type, emailConst.type.RECEIVE));
}
if (type === 'delete') {
conditions.push(eq(email.isDel, isDel.DELETE));
}
if (type === 'noone') {
conditions.push(eq(email.status, emailConst.status.NOONE));
}
if (userEmail) {
conditions.push(sql`${user.email} COLLATE NOCASE LIKE ${'%' + userEmail + '%'}`);
}
if (accountEmail) {
conditions.push(
or(
sql`${email.toEmail} COLLATE NOCASE LIKE ${'%' + accountEmail + '%'}`,
sql`${email.sendEmail} COLLATE NOCASE LIKE ${'%' + accountEmail + '%'}`,
)
);
}
if (name) {
conditions.push(sql`${email.name} COLLATE NOCASE LIKE ${'%' + name + '%'}`);
}
if (subject) {
conditions.push(sql`${email.subject} COLLATE NOCASE LIKE ${'%' + subject + '%'}`);
}
conditions.push(ne(email.status, emailConst.status.SAVING));
if (withCursor && emailId) {
conditions.push(timeSort ? gt(email.emailId, emailId) : lt(email.emailId, emailId));
}
return conditions;
},
async delete(c, params, userId) {
const { emailIds } = params;
const emailIdList = emailIds.split(',').map(Number);
@@ -750,7 +793,7 @@ const emailService = {
}
let list = await orm(c).select({...email}).from(email)
.leftJoin(
.innerJoin(
account,
eq(account.accountId, email.accountId)
)
@@ -760,7 +803,7 @@ const emailService = {
eq(email.userId, userId),
eq(email.isDel, isDel.NORMAL),
eq(account.isDel, isDel.NORMAL),
allReceive ? eq(1,1) : eq(email.accountId, accountId),
allReceive ? undefined : eq(email.accountId, accountId),
eq(email.type, emailConst.type.RECEIVE)
))
.orderBy(desc(email.emailId))
@@ -815,81 +858,25 @@ const emailService = {
size = Number(size);
emailId = Number(emailId);
emailId = Number(emailId) || 0;
timeSort = Number(timeSort);
if (size > 50) {
size = 50;
}
if (!emailId) {
if (timeSort) {
emailId = 0;
} else {
emailId = 9999999999;
}
}
const conditions = [];
if (type === 'send') {
conditions.push(eq(email.type, emailConst.type.SEND));
}
if (type === 'receive') {
conditions.push(eq(email.type, emailConst.type.RECEIVE));
}
if (type === 'delete') {
conditions.push(eq(email.isDel, isDel.DELETE));
}
if (type === 'noone') {
conditions.push(eq(email.status, emailConst.status.NOONE));
}
if (userEmail) {
conditions.push(sql`${user.email} COLLATE NOCASE LIKE ${'%'+ userEmail + '%'}`);
}
if (accountEmail) {
conditions.push(
or(
sql`${email.toEmail} COLLATE NOCASE LIKE ${'%'+ accountEmail + '%'}`,
sql`${email.sendEmail} COLLATE NOCASE LIKE ${'%'+ accountEmail + '%'}`,
)
)
}
if (name) {
conditions.push(sql`${email.name} COLLATE NOCASE LIKE ${'%'+ name + '%'}`);
}
if (subject) {
conditions.push(sql`${email.subject} COLLATE NOCASE LIKE ${'%'+ subject + '%'}`);
}
conditions.push(ne(email.status, emailConst.status.SAVING));
const countConditions = [...conditions];
if (timeSort) {
conditions.unshift(gt(email.emailId, emailId));
} else {
conditions.unshift(lt(email.emailId, emailId));
}
const filters = this.allEmailListFilters({ emailId, name, subject, accountEmail, userEmail, type, timeSort });
const countFilters = this.allEmailListFilters({ emailId, name, subject, accountEmail, userEmail, type, timeSort, withCursor: false });
const query = orm(c).select({ ...email, userEmail: user.email })
.from(email)
.leftJoin(user, eq(email.userId, user.userId))
.where(and(...conditions));
.where(and(...filters));
const queryCount = orm(c).select({ total: count() })
.from(email)
.leftJoin(user, eq(email.userId, user.userId))
.where(and(...countConditions));
.where(and(...countFilters));
if (timeSort) {
query.orderBy(asc(email.emailId));
+2 -6
View File
@@ -42,13 +42,9 @@ const starService = {
async list(c, params, userId) {
let { emailId, size } = params;
emailId = Number(emailId);
emailId = Number(emailId) || 0;
size = Number(size);
if (!emailId) {
emailId = 9999999999;
}
const list = await orm(c).select({
isStar: sql`1`.as('isStar'),
starId: star.starId
@@ -59,7 +55,7 @@ const starService = {
and(
eq(star.userId, userId),
eq(email.isDel, isDel.NORMAL),
lt(star.emailId, emailId)))
emailId ? lt(star.emailId, emailId) : undefined))
.orderBy(desc(star.emailId))
.limit(size)
.all();