对于以下MariaDB模式:
元模式版本
- 识别码(整数)
- 名称空间标识(int)
- 版本(varchar(10))
- 结构描述(长文字)
- 注解(中文本)
- 创建时间(日期时间)
元数据 - 标识(整数)[主键]
- 元标识符(整数)
- 版本编号(整数)
- 元模式版本标识(整数)- [FK到元模式版本]
- 标签(varchar(30))
- 标记值(varchar(100))
- 元(长文本)
- 注解(中文本)
- 被删除(tinyint(1))
- updated_at(日期时间)
- 更新者(varchar(100))
以下是meta表上的索引:
- id -主键- BTREE -唯一
- meta_schema_version_id -外键- BTREE -不唯一
- idx配置标识- BTREE -不唯一
meta表中有一百多万条记录。
我使用Sequelize来获取一个分页列表,如下所示:
metas = await this.meta.findAndCountAll({
attributes: ['id', 'tag', 'tagValue', ...versionAttribute],
include: [
{
model: MetaSchemaVersion,
attributes: ['version'],
},
],
where: {
metaSchemaVersionId: schemaVersion.id,
isDeleted: {
[Op.eq]: 0,
},
},
limit,
offset,
});
Sequelize会记录与上述函数对应的以下2个查询:查询1:
SELECT count(*) AS `count`
FROM `meta` AS `Meta`
WHERE `Meta`.`meta_schema_version_id` = 1
AND `Meta`.`is_deleted` = 0
查询2:
SELECT `id`, `tag`, `tag_value` AS `tagValue`,
`comment`, `updated_at` AS `updatedAt`,
`updated_by` AS `updatedBy`,
`meta_schema_version_id` AS `metaSchemaVersionId`,
`meta`
FROM `meta` AS `Meta`
WHERE `Meta`.`meta_schema_version_id` = 1
AND `Meta`.`is_deleted` = 0
LIMIT 0, 10
我启用了非常低的long_query_time(0.0001)的慢速查询日志
慢速查询日志的查询时间为:
- 查询1:00:00:00.612878
- 查询2:00:00:00.894041
当直接在CLI上运行相同的查询时,两个查询的查询时间都显示为**~00:00:00.0005**
为什么直接在CLI上运行与通过Sequelize ORM运行在查询时间上会有如此大的差异?
SHOW PROFILE对慢速查询给出以下响应
[
{ Status: 'Starting', Duration: '0.000026' },
{ Status: 'Opening tables', Duration: '0.000025' },
{ Status: 'System lock', Duration: '0.000003' },
{ Status: 'table lock', Duration: '0.000004' },
{ Status: 'Opening tables', Duration: '0.000002' },
{ Status: 'After opening tables', Duration: '0.000100' },
{ Status: 'closing tables', Duration: '0.000003' },
{ Status: 'Unlocking tables', Duration: '0.000003' },
{ Status: 'closing tables', Duration: '0.000073' },
{ Status: 'checking permissions', Duration: '0.000005' },
{ Status: 'Opening tables', Duration: '0.000013' },
{ Status: 'After opening tables', Duration: '0.000004' },
{ Status: 'System lock', Duration: '0.000004' },
{ Status: 'table lock', Duration: '0.000006' },
{ Status: 'init', Duration: '0.000033' },
{ Status: 'Optimizing', Duration: '0.000018' },
{ Status: 'Statistics', Duration: '0.000074' },
{ Status: 'Preparing', Duration: '0.000024' },
{ Status: 'Executing', Duration: '0.000002' },
{ Status: 'Sending data', Duration: '0.880704' },
{ Status: 'End of update loop', Duration: '0.000016' },
{ Status: 'Query end', Duration: '0.000003' },
{ Status: 'Commit', Duration: '0.000005' },
{ Status: 'closing tables', Duration: '0.000003' },
{ Status: 'Unlocking tables', Duration: '0.000002' },
{ Status: 'closing tables', Duration: '0.000043' },
{ Status: 'Starting cleanup', Duration: '0.000003' },
{ Status: 'Freeing items', Duration: '0.000010' },
{ Status: 'Updating status', Duration: '0.000015' },
{ Status: 'Logging slow query', Duration: '0.000006' },
{ Status: 'Opening tables', Duration: '0.000016' },
{ Status: 'System lock', Duration: '0.000002' },
{ Status: 'table lock', Duration: '0.000003' },
{ Status: 'Opening tables', Duration: '0.000002' },
{ Status: 'After opening tables', Duration: '0.000059' },
{ Status: 'closing tables', Duration: '0.000002' },
{ Status: 'Unlocking tables', Duration: '0.000002' },
{ Status: 'closing tables', Duration: '0.000005' },
{ Status: 'Reset for next command', Duration: '0.000238' }
]
更新1:我的原始帖子中提到的查询是不正确的。我在复制SQL查询时已经在ORM代码中注解了连接部分。正确的查询是:
查询1:
SELECT count(Meta.id) AS count FROM meta AS Meta LEFT OUTER JOIN meta_schema_version AS metaSchemaVersion ON Meta.meta_schema_version_id = metaSchemaVersion.id WHERE Meta.meta_schema_version_id = 1 AND Meta.is_deleted = 0;
查询2:
SELECT Meta.id, Meta.tag, Meta.tag_value AS tagValue, Meta.comment, Meta.updated_at AS updatedAt, Meta.updated_by AS updatedBy, Meta.meta_schema_version_id AS metaSchemaVersionId, Meta.meta, metaSchemaVersion.id AS metaSchemaVersion.id, metaSchemaVersion.version AS metaSchemaVersion.version FROM meta AS Meta LEFT OUTER JOIN meta_schema_version AS metaSchemaVersion ON Meta.meta_schema_version_id = metaSchemaVersion.id WHERE Meta.meta_schema_version_id = 1 AND Meta.is_deleted = 0 LIMIT 0, 20;
1条答案
按热度按时间moiiocjp1#
这可能对两个查询的
Meta
都有利:但是,没有
ORDER BY
的LIMIT
将给出它想要给出的任何行。(我对X1 M5 N1 X有非常负面的看法。注意几乎所有的时间都在神秘的“发送数据”中。这很常见。)
直接在CLI上运行时的相同查询
这有两个 * 可能 * 的原因。
因此,添加该标志,运行查询两次,进行第二次计时。
我从本地开发机器上的应用服务器发出请求。
测试网络延迟(开销)的一种方法是对简单的
SELECT 1;
查询进行计时。查询1必须扫描整个表。使用我的索引,它将扫描索引的一部分。
查询2(没有
ORDER BY
)扫描表,直到找到10行与WHERE
子句匹配。