简体   繁体   English

提高具有一对多关系的 MYSQL 查询的性能

[英]Improving the performance of a MYSQL query with a one-to-many relationship

I have a query in my DB that is taking 25 seconds to return results, which is way too long.我的数据库中有一个查询需要 25 秒才能返回结果,这太长了。 It seems like it should be pretty simple.看起来应该很简单。 Two tables;两张桌子; the main table (document) is a standard table with some data columns, the join table is a mapping table with only two columns (parent_id, division_id).主表(文档)是标准表,有一些数据列,连接表是只有两列(parent_id,division_id)的映射表。 Previously there wasn't an index on the mapping table so I added one and that changed the "explain" to include the index but doesn't seem to have had an impact on the performance.以前映射表上没有索引,所以我添加了一个,并更改了“解释”以包含索引,但似乎对性能没有影响。

The query looks like this:查询如下所示:

explain SELECT DISTINCT doc.*  
FROM document doc  
LEFT JOIN multi_division_mapper divisions ON doc.id = divisions.parent_id  
WHERE doc.clientId = 'SOME_GUID'  
AND (divisions.division_id IS NULL OR divisions.division_id  IN ('SOME_GUID'));

and the results of explain are:解释的结果是: 在此处输入图像描述

Total number of rows in document: 6720 Total number of rows in mapper: 6173文档中的总行数:6720 映射器中的总行数:6173

From what I've been able to gather I need to improve either the "type" or the "extra" to make the query faster.根据我收集到的信息,我需要改进“类型”或“额外”以使查询更快。 What can I do here?我可以在这里做什么?

Create table statements:建表语句:

CREATE TABLE `document` (
   `id` varchar(36) NOT NULL,
   `addedBy` varchar(255) DEFAULT NULL,
   `addedDate` datetime NOT NULL,
   `editedBy` varchar(255) DEFAULT NULL,
   `editedDate` datetime NOT NULL,
   `deleted` bit(1) DEFAULT NULL,
   `clientId` varchar(36) NOT NULL,
   `departmentId` varchar(36) DEFAULT NULL,
   `documentParentId` varchar(36) DEFAULT NULL,
   `documentParent` varchar(50) DEFAULT NULL,
   `fileId` varchar(255) DEFAULT NULL,
   `fileUrl` varchar(600) DEFAULT NULL,
   `documentName` varchar(500) NOT NULL,
   `displayName` varchar(255) NOT NULL,
   `documentId` varchar(45) DEFAULT NULL,
   `notes` varchar(1000) DEFAULT NULL,
   `visibility` varchar(45) NOT NULL DEFAULT 'PRIVATE',
   `documentType` varchar(45) NOT NULL,
   `restrictDelete` bit(1) NOT NULL,
   `customData` text,
   `releaseDate` datetime NOT NULL,
   `expirationDate` datetime NOT NULL,
   `isApproved` bit(1) NOT NULL DEFAULT b'0',
   `userSupplier` varchar(36) DEFAULT NULL,
   `complianceCertificateId` varchar(36) DEFAULT NULL,
   `Status` varchar(50) DEFAULT 'NEUTRAL',
   PRIMARY KEY (`id`),
   KEY `idx_client` (`clientId`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
 CREATE TABLE `multi_division_mapper` (
    `parent_id` varchar(36) NOT NULL,
    `division_id` varchar(36) NOT NULL,
    PRIMARY KEY (`parent_id`,`division_id`),
    KEY `idx_parent` (`parent_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

I was able to get a more favorable EXPLAIN report in a test by creating the following index:通过创建以下索引,我能够在测试中获得更有利的 EXPLAIN 报告:

ALTER TABLE multi_division_mapper
  DROP INDEX idx_parent,
  ADD INDEX (division_id, parent_id);

I also dropped idx_parent because it's redundant;我也删除了idx_parent因为它是多余的; it's a prefix of the primary key.它是主键的前缀。

id ID select_type选择类型 table桌子 partitions分区 type类型 possible_keys可能的键 key钥匙 key_len密钥长度 ref参考 rows filtered过滤 Extra额外的
1 1个 SIMPLE简单的 doc文件 NULL NULL ref参考 idx_client idx_client idx_client idx_client 110 110 const常数 1 1个 100.00 100.00 Using temporary使用临时
1 1个 SIMPLE简单的 divisions NULL NULL ref参考 PRIMARY,division_id主要的,division_id division_id部门编号 38 38 const常数 1 1个 100.00 100.00 Using where;在哪里使用; Using index;使用索引; Distinct清楚的

The type: ref is better than type: index . type: ref优于type: index

The query I tested is slightly different, but I believe it returns the same result:我测试的查询略有不同,但我相信它会返回相同的结果:

SELECT DISTINCT  doc.*   
FROM document doc   
LEFT JOIN multi_division_mapper divisions
  ON doc.id = divisions.parent_id AND divisions.division_id in ('SOME_GUID')  
WHERE doc.clientId = 'SOME_GUID'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM