MariaDB에서 동일한 쿼리를 애플리케이션에서 Sequitize를 통해 실행할 때 mysql 클라이언트 또는 CLI에서 직접 실행할 때보다 시간이 더 오래 걸리는 이유는 무엇입니까?
다음 MariaDB 스키마의 경우:
meta_meta_version
- id(int)
- namespace_id(int)
- 버전(varchar(10))
- 스키마(긴 텍스트)
- 주석(중간 텍스트)
- created_at(날짜 시간)
메타의
- id (int) [PK]
- meta_id(int)
- version_num (int)
- meta_schema_version_id(int) - [FK to meta_schema_version]
- 태그(varchar(30))
- tag_value(varchar(100))
- 메타(긴 텍스트)
- 주석(중간 텍스트)
- is_messages(1)
- update_at(날짜 시간)
- updated_by(varchar(100))
메타 테이블의 인덱스는 다음과 같습니다.
- id - 기본 키 - BTREE - 고유
- meta_schema_version_id - 외부 키 - BTREE - 고유하지 않음
- idx_config_id - BTREE - 고유하지 않음
메타 테이블에는 백만 개 이상의 레코드가 있습니다.
다음과 같은 페이지 목록을 가져오기 위해 Sequetize를 사용하고 있습니다.
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,
});
Sequitize는 위 기능에 해당하는 쿼리 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.0005로 표시합니다.
Sequetize ORM을 통해 CLI에서 직접 실행할 때와 Sequetize 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;
이것은 도움이 될 수 있습니다.Meta
두 쿼리 모두에 대해:
INDEX(meta_schema_version_id, is_deleted) -- (the column order does not matter)
그러나, a.LIMIT
무턱내지 않고ORDER BY
무슨 일이 일어나든 당신에게 줄 것입니다추가하는 경우ORDER BY
최적의 상태를 재분석해야 합니다.INDEX
(저는 매우 부정적인 의견을 가지고 있습니다.Profile
거의 모든 시간이 암호화된 "데이터 전송"에서 발생합니다.이것은 일반적입니다.)
CLI에서 직접 실행할 때 동일한 쿼리
그것에 대한 두 가지 가능한 이유가 있습니다.다음과 같이 쿼리를 실행할 것을 권장합니다.
SELECT SQL_NO_CACHE ...`
- 이렇게 하면 쿼리와 쿼리 결과가 캐시되는 "쿼리 캐시"를 피할 수 있습니다. 두 번째 실행은 기본적으로 00:00:00.0005와 같이 즉시 실행되기 때문입니다.
- 또는... 첫 번째 실행에서는 디스크에서 많은 데이터를 가져와 RAM에 캐시된 데이터 때문에 두 번째 실행 속도가 훨씬 빨라졌을 수 있습니다.
플래그를 추가하고 쿼리를 두 번 실행한 다음 두 번째 타이밍을 잡습니다.
저는 제 로컬 개발 기계의 앱 서버에서 요청을 하고 있습니다.
네트워크 지연 시간(오버헤드)을 테스트하는 한 가지 방법은 사소한 시간을 측정하는 것입니다.SELECT 1;
질의하다
쿼리 1은 전체 테이블을 검색해야 합니다.내 색인을 사용하면 색인의 일부를 검색합니다.
쿼리 2, 다음을 제외합니다.ORDER BY
테이블이 일치하는 10개의 행을 찾을 때까지 테이블을 스캔합니다.WHERE
절
언급URL : https://stackoverflow.com/questions/73496328/why-is-the-same-query-on-mariadb-taking-more-time-when-run-via-sequelize-from-th
'source' 카테고리의 다른 글
설명에 대한 실행 컨텍스트를 찾거나 만들지 못했습니다. (0) | 2023.06.13 |
---|---|
C에서 환경 변수 설정 (0) | 2023.06.08 |
mysql-10.4.24-MariaDB의 REGEXP_REPLACE를 사용하여 문자열에서 및 I의 allocurance를 제거하려면 어떻게 해야 합니까? (0) | 2023.06.08 |
자신의 함수를 작성할 때 R의 생략 부호 기능을 사용하는 방법은 무엇입니까? (0) | 2023.06.08 |
Vue & Vuex를 사용하여 필드 편집 (0) | 2023.06.08 |