programing

외부 키를 사용하는 MariaDB 내부 조인은 키를 사용하지 않는 것보다 훨씬 느립니다.

i4 2023. 8. 19. 09:45
반응형

외부 키를 사용하는 MariaDB 내부 조인은 키를 사용하지 않는 것보다 훨씬 느립니다.

마리아DB 서버의 이상한 행동에 꼼짝 못하고 있으니 도와주세요.3개의 테이블이 있습니다.

CREATE TABLE `default_work` (
  `add_date` datetime(6) NOT NULL,
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `keywords` varchar(255) DEFAULT NULL,
  `short_text` longtext DEFAULT NULL,
  `downloads` int(10) unsigned NOT NULL,
  `published` tinyint(1) NOT NULL,
  `subject_id` int(11) NOT NULL,
  `work_type_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `default_work_subject_id_IDX` (`subject_id`) USING BTREE,
  KEY `default_work_work_type_id_IDX` (`work_type_id`) USING BTREE,
  CONSTRAINT `default_work_FK` FOREIGN KEY (`subject_id`) REFERENCES `default_subject` (`id`),
  CONSTRAINT `default_work_FK_1` FOREIGN KEY (`work_type_id`) REFERENCES `default_worktype` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=210673 DEFAULT CHARSET=utf8

CREATE TABLE `default_subject` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `subject` varchar(255) NOT NULL,
  `old_id` int(10) unsigned NOT NULL,
  `subject_literal` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8

CREATE TABLE `default_worktype` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `work_type` varchar(250) NOT NULL,
  `description` longtext DEFAULT NULL,
  `old_id` int(10) unsigned NOT NULL,
  `work_type_literal` varchar(250) NOT NULL,
  `title` varchar(255) NOT NULL,
  `multiple` varchar(255) NOT NULL,
  `keywords` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `default_worktype_old_id_a8b508fe_uniq` (`old_id`),
  UNIQUE KEY `default_worktype_work_type_literal_1e609434_uniq` (`work_type_literal`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8

이 테이블들은 Django ORM에 의해 만들어졌지만 괜찮은 것 같습니다.default_work 테이블에는 약 200,000개의 레코드, default_subject - 42 및 default_worktype - 12가 있습니다.

장고 관리자에서 테이블 간의 간단한 조인으로 요청한 후 약 9초의 쿼리 시간이 있습니다.SQL 로그에서 원시 쿼리를 찾았습니다.

SELECT `default_work`.`id`, `default_work`.`title`, `default_worktype`.`work_type`,`default_subject`.`subject`
FROM `default_work`
INNER JOIN `default_subject` ON (`default_work`.`subject_id` = `default_subject`.`id`)
INNER JOIN `default_worktype` ON (`default_work`.`work_type_id` = `default_worktype`.`id`) 
ORDER BY `default_work`.`id` DESC LIMIT 100

표시되는 설명: 인덱스를 사용하여 쿼리 결과 설명

그리고 기본 키를 제외한 테이블 default_work의 모든 인덱스를 삭제했을 때 결과가 완전히 달랐기 때문에 약간 혼란스럽습니다.요청 시간은 약 3.4msec이며 모든 기본 키가 올바르게 사용되고 있음을 설명합니다.인덱스가 없는 쿼리 결과 설명

PS. 저는 이 상황을 Postgre에서 재현하려고 합니다.SQL과 인덱스 및 외부 키가 포함된 요청으로 1.3msec을 받았습니다.

EXPLE 결과를 보면 외부 키를 켜면 시스템이 대상 테이블에서 기본 키를 사용하도록 선택하는 대신 조인에서 해당 키를 사용하고 있음을 알 수 있습니다.(2열)

동일한 값을 가진 많은 레코드가 있을 것이므로 평가되는 레코드가 대량으로 증가합니다.

저는 왜 그것을 선택하는지 모르겠습니다.선택 문을 다른 순서로 다시 작성하면 인덱스 선택 방법이 변경될 수 있습니다.ON 절에서 대상 테이블을 먼저 지정하고 소스 테이블(default_subject.id=default_work.subject_id)

언급URL : https://stackoverflow.com/questions/57393045/mariadb-inner-join-with-foreign-keys-are-much-slower-than-without-them

반응형