在查询优化方面需要帮助

need help in query optimization

我有以下查询需要很长时间才能执行,因为它有 OR opeartion.Here 机构 59958 是一个全球机构。它本身可以有统计数据,它的 children 也可以有统计数据;所以 'parentinstitutionid' 对于 59958 或 institutionid 59958 我们需要使用数据 for.so 我正在使用 OR opeartor。

  select date(SUBDATE(m.timestamp, INTERVAL (day(m.timestamp) -1) day)) as month, 
       count(*) as c,
       sum(case when a.streamid = 5 then 1 else 0 end) as education,
       sum(case when a.streamid in(7, 1) then 1 else 0 end) as research,
       sum(case when searchterms <> '' then 1 else 0 end) as search
from stats_to_institution as s
join masterstats_innodb as m on s.statid = m.id
left join articles as a on (a.productid >= 49 and a.productid = m.article)
where m.timestamp >= '2022-01-01' 
and (s.institutionid = 59958 or s.institutionid in ( select institutionid from institutions where parentinstitutionid = 59958))
group by month;

以下情况需要时间 (s.institutionid = 59958 或 s.institutionid in (select institutionid from institutions where parentinstitutionid = 59958))

我无法使用 5.6 上的 CTE version.Is 是否有任何其他方法可以修改上述条件以获得良好的性能?。 如果我删除 s.institutionid = 59958 它只需要 5 秒到 运行 因为它不会有 OR 运算符。

对此有什么建议吗?

table结构如下

CREATE TABLE `institutions` (
  `InstitutionID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` varchar(200) DEFAULT NULL,
  `Approved` tinyint(1) NOT NULL DEFAULT '0',
  `DateAdded` datetime DEFAULT CURRENT_TIMESTAMP,
  `IsAcademic` tinyint(1) DEFAULT NULL,
  `IsIndustry` tinyint(1) DEFAULT NULL,
  `LogoFile` varchar(50) DEFAULT NULL,
  `NotifyLibEveryXRequests` int(11) DEFAULT NULL,
  `IsParentInstitution` int(1) NOT NULL DEFAULT '0',
  `ParentInstitutionID` int(11) DEFAULT NULL,
  PRIMARY KEY (`InstitutionID`),
  KEY `Institutions_Name` (`Name`),
  KEY `ParentInstitutionID` (`ParentInstitutionID`),
  FULLTEXT KEY `Name` (`Name`)
) ;


CREATE TABLE `masterstats_innodb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `page` text COLLATE utf8_unicode_ci NOT NULL,
  `video` int(11) NOT NULL,
  `language` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `referrer` text COLLATE utf8_unicode_ci NOT NULL,
  `joveuser` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
  `timestamp` date NOT NULL DEFAULT '0000-00-00',
  PRIMARY KEY (`id`,`timestamp`),
  KEY `joveuser` (`joveuser`),
  KEY `institutionid` (`institutionid`),
  KEY `timestamp` (`timestamp`),
  KEY `idx__video_timestamp` (`video`,`timestamp`)
) ;

CREATE TABLE `stats_to_institution` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `statid` int(11) NOT NULL,
  `institutionid` int(11) NOT NULL,
  PRIMARY KEY (`id`,`institutionid`),
  UNIQUE KEY `statid_2` (`statid`,`institutionid`),
  KEY `statid` (`statid`),
  KEY `institutionid` (`institutionid`)
) ;

CREATE TABLE `articles` (
  `ProductID` int(11) NOT NULL,
  `Name` varchar(1000) DEFAULT NULL,
  `Tags` varchar(1000) NOT NULL,
  `D` varchar(2000) DEFAULT NULL,
  `Active` tinyint(1) DEFAULT NULL,
  `UserID` int(11) DEFAULT NULL,
  `DateAdded` datetime DEFAULT NULL,
  `Detail_Abstract` text,
  `StreamID` int(11) DEFAULT NULL COMMENT '-1 = Errata, 1= Article, 2= Advertisment, 3 = Editorial, 4= Junk, 5=SE',
  `DatePublished` datetime DEFAULT NULL,
  `AccessType` int(11) DEFAULT NULL COMMENT '-1=Unpublished, 0=Closed, 1=Free, 2=Open, 3 = Open UK',
  `Rep_Results` text,
  `Stage` int(11) DEFAULT NULL,
  `SectionID` int(11) DEFAULT NULL,
  PRIMARY KEY (`ProductID`),
  KEY `Articles_StreamID_Active_DatePublished` (`StreamID`,`Active`,`DatePublished`),
  KEY `articles_idx_sectionid` (`SectionID`),
  FULLTEXT KEY `DetailAbstractTest` (`Detail_Abstract`,`Name`),
  FULLTEXT KEY `Materials` (`Materials`),
  FULLTEXT KEY `title` (`Name`)
);

解释结果

+----+-------------+--------------+--------+------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------+-----------------+----------+----------------------------------------------+
| id | select_type | table        | type   | possible_keys                                                                                                                            | key                 | key_len | ref             | rows     | Extra                                        |
+----+-------------+--------------+--------+------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------+-----------------+----------+----------------------------------------------+
|  1 | PRIMARY     | m            | ALL    | PRIMARY,timestamp_video,joveuser,institutionid,video_institutionid,user_id,ip_binary,time_on_page,Article,timestamp,idx__video_timestamp | NULL                | NULL    | NULL            | 19653526 | Using where; Using temporary; Using filesort |
|  1 | PRIMARY     | a            | eq_ref | PRIMARY                                                                                                                                  | PRIMARY             | 4       | stats.m.Article |        1 | Using where                                  |
|  1 | PRIMARY     | s            | ref    | statid_2,statid,institutionid                                                                                                            | statid_2            | 4       | stats.m.id      |        1 | Using where; Using index                     |
|  2 | SUBQUERY    | institutions | ref    | PRIMARY,ParentInstitutionID                                                                                                              | ParentInstitutionID | 5       | const           |      173 | Using index                                  |
+----+-------------+--------------+--------+------------------------------------------------------------------------------------------------------------------------------------------+---------------------+---------+-----------------+----------+----------------------------------------------+

没有CTE,加入怎么样?

select date(SUBDATE(m.timestamp, INTERVAL (day(m.timestamp) -1) day)) as month, 
       count(*) as c,
       sum(case when a.streamid = 5 then 1 else 0 end) as education,
       sum(case when a.streamid in(7, 1) then 1 else 0 end) as research,
       sum(case when searchterms <> '' then 1 else 0 end) as search
from stats_to_institution as s
join (select institutionid 
      from institutions 
      where parentinstitutionid = 59958
     union all select 59998 
     ) x on x.institutionid = s.institutionid
join masterstats_innodb as m on s.statid = m.id
left join articles as a on (a.productid >= 49 and a.productid = m.article)
where m.timestamp >= '2022-01-01' 
group by month;