Browse Source

Fix slow query on large page of judge_state

master
Menci 6 years ago
parent
commit
c9f03f2a2e
  1. 27
      models/common.js
  2. 2
      modules/submission.js

27
models/common.js

@ -99,7 +99,7 @@ class Model {
return this.model.count({ where: where }); return this.model.count({ where: where });
} }
static async query(paginate, where, order) { static async query(paginate, where, order, largeData) {
let records = []; let records = [];
if (typeof paginate === 'string') { if (typeof paginate === 'string') {
@ -121,11 +121,34 @@ class Model {
options.limit = parseInt(paginate.perPage); options.limit = parseInt(paginate.perPage);
} }
records = await this.model.findAll(options); if (!largeData) records = await this.model.findAll(options);
else {
let sql = await getSqlFromFindAll(this.model, options);
let i = sql.indexOf('FROM');
sql = 'SELECT id ' + sql.substr(i, sql.length - i);
sql = `SELECT a.* FROM (${sql}) AS b JOIN ${this.model.name} AS a ON a.id = b.id ORDER BY id DESC`;
records = await syzoj.db.query(sql, { model: this.model });
}
} }
return records.mapAsync(record => (this.fromRecord(record))); return records.mapAsync(record => (this.fromRecord(record)));
} }
} }
function getSqlFromFindAll(Model, options) {
let id = require('uuid')();
return new Promise((resolve, reject) => {
Model.addHook('beforeFindAfterOptions', id, options => {
Model.removeHook('beforeFindAfterOptions', id);
resolve(Model.sequelize.dialect.QueryGenerator.selectQuery(Model.getTableName(), options, Model).slice(0, -1));
return new Promise(() => {});
});
return Model.findAll(options).catch(reject);
});
}
module.exports = Model; module.exports = Model;

2
modules/submission.js

@ -113,7 +113,7 @@ app.get('/submissions', async (req, res) => {
} }
let paginate = syzoj.utils.paginate(await JudgeState.count(where), req.query.page, syzoj.config.page.judge_state); let paginate = syzoj.utils.paginate(await JudgeState.count(where), req.query.page, syzoj.config.page.judge_state);
let judge_state = await JudgeState.query(paginate, where, [['id', 'desc']]); let judge_state = await JudgeState.query(paginate, where, [['id', 'desc']], true);
await judge_state.forEachAsync(async obj => obj.loadRelationships()); await judge_state.forEachAsync(async obj => obj.loadRelationships());

Loading…
Cancel
Save