繁体   English   中英

任何使用大数据更快地执行此查询的方法

[英]Any way to do this query faster with big data

这个查询大约需要 2.23 秒,感觉有点慢......无论如何可以让它更快。 我们的 member.id、member_id、membership_id、valid_to、valid_from 也有索引。

select * 
from member 
where (member.id in ( select member_id from member_membership mm 
INNER JOIN membership m ON mm.membership_id = m.id 
where instr(organization_chain, 2513) and m.valid_to > NOW() and m.valid_from < NOW() ) ) 
order by id desc 
limit 10 offset 0

查询做什么的解释:每个成员都有许多成员成员成员,并且成员成员成员与另一个名为成员资格的表连接,我们有成员资格详细信息。 因此查询将获取所有具有有效成员资格的成员以及组织 ID 2513 存在于 member_membership 的位置。 表如下:

CREATE TABLE `member` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

CREATE TABLE `member_membership` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `membership_id` int(11) DEFAULT NULL,
  `member_id` int(11) DEFAULT NULL,
  `organization_chain` text DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `member_membership_to_membership` (`membership_id`),
  KEY `member_membership_to_member` (`member_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

CREATE TABLE `membership` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `valid_to` datetime DEFAULT NULL,
  `valid_from` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `valid_to` (`valid_to`),
  KEY `valid_from` (`valid_from`),
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

ALTER TABLE `member_membership` ADD CONSTRAINT `member_membership_to_membership` FOREIGN KEY (`membership_id`) REFERENCES `membership` (`id`);

ALTER TABLE `member_membership` ADD CONSTRAINT `member_membership_to_member` FOREIGN KEY (`member_id`) REFERENCES `member` (`id`);

这里有 EXPLAIN 语句 => https://i.ibb.co/xjrcYWR/EXPLAIN.png

关系

  • 会员有很多member_membership
  • 会员有 manymember_membership
  • 所以 member_membership 就像表 member 和 members 的 join 。

好吧,我找到了一种方法可以将其缩短到 800 毫秒……就像这样。 这是好方法还是我们可以做的更多?

select * 
from member  
where (member.id in ( select member_id from member_membership mm FORCE INDEX (PRIMARY)
INNER JOIN membership m ON mm.membership_id = m.id  
where instr(organization_chain, 2513) and m.valid_to > NOW() and m.valid_from < NOW() ) ) 
order by id desc 
limit 10 offset 0

新更新.. 我认为这解决了问题.. 15 毫秒 :) 我添加了 FORCE INDEX.. FORCE INDEX 提示的作用类似于 USE INDEX (index_list),此外还认为表扫描非常昂贵。 换句话说,仅当无法使用命名索引之一来查找表中的行时才使用表扫描。

 select * 
from member  
where (member.id in ( select member_id from member_membership mm FORCE INDEX (member_membership_to_member)
INNER JOIN membership m FORCE INDEX (organization_to_membership) ON mm.membership_id = m.id  
where instr(organization_chain, 2513) and m.valid_to > NOW() and m.valid_from < NOW() ) ) 
order by id desc 
limit 10 offset 0

organization_chain有多大? 如果您不需要TEXT ,请使用合理大小的VARCHAR以便它可以在索引中。 更好的是,是否有某种方法可以单独在列中获得 2513?

不要在多对多表中使用id int(11) NOT NULL AUTO_INCREMENT, 而是在PRIMARY KEY有两列。

ORDER BYLIMIT放在子查询中。

不要使用IN ( SELECT ...) ,使用JOIN

暂无
暂无

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

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