简体   繁体   English

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

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

This query takes around 2.23seconds and feels a bit slow ... is there anyway to make it faster.这个查询大约需要 2.23 秒,感觉有点慢......无论如何可以让它更快。 our member.id, member_id, membership_id, valid_to, valid_from has index as well.我们的 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

EXPLAIN FOR WHAT QUERY DOING: every member has many a member_memberships and and member_memberships connect with another table called membership there we have the membership details.查询做什么的解释:每个成员都有许多成员成员成员,并且成员成员成员与另一个名为成员资格的表连接,我们有成员资格详细信息。 so query will get all members that has valid memberships and where the organization id 2513 exist on member_membership.因此查询将获取所有具有有效成员资格的成员以及组织 ID 2513 存在于 member_membership 的位置。 Tables as following:表如下:

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`);

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

Relations关系

  • member has many member_membership会员有很多member_membership
  • membership has manymember_membership会员有 manymember_membership
  • So member_membership is like join for tables member and membership.所以 member_membership 就像表 member 和 members 的 join 。

Well I found a way to make it less to 800ms ... like this.好吧,我找到了一种方法可以将其缩短到 800 毫秒……就像这样。 Is this good way or maybe there is more we can do?这是好方法还是我们可以做的更多?

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

NEW UPDATE.. and I think this solve the issue.. 15ms :) I added FORCE INDEX.. The FORCE INDEX hint acts like USE INDEX (index_list), with the addition that a table scan is assumed to be very expensive.新更新.. 我认为这解决了问题.. 15 毫秒 :) 我添加了 FORCE INDEX.. FORCE INDEX 提示的作用类似于 USE INDEX (index_list),此外还认为表扫描非常昂贵。 In other words, a table scan is used only if there is no way to use one of the named indexes to find rows in the table.换句话说,仅当无法使用命名索引之一来查找表中的行时才使用表扫描。

 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

How big is organization_chain ? organization_chain有多大? If you don't need TEXT , use a reasonably sized VARCHAR so that it could be in an index.如果您不需要TEXT ,请使用合理大小的VARCHAR以便它可以在索引中。 Better yet, is there some way to get 2513 in a column by itself?更好的是,是否有某种方法可以单独在列中获得 2513?

Don't use id int(11) NOT NULL AUTO_INCREMENT, in a many-to-many table;不要在多对多表中使用id int(11) NOT NULL AUTO_INCREMENT, rather have the two columns in PRIMARY KEY .而是在PRIMARY KEY有两列。

Put the ORDER BY and LIMIT in the subquery.ORDER BYLIMIT放在子查询中。

Don't use IN ( SELECT ...) , use a JOIN .不要使用IN ( SELECT ...) ,使用JOIN

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

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