如何加快条件MYSQL查询

时间:2018-09-05 17:44:51

标签: mysql

查询是:

SELECT RP.pID
  , (IF(RI.p01 = 54, 1, 0)
     + IF(RI.p02 = 16, 1, 0)
     + IF(RI.p03 = 54, 1, 0)
     + IF(RI.p04 = 92, 1, 0)
     + IF(RI.p05 = 34, 1, 0)
     + IF(RI.p06 = 51, 1, 0)
     + IF(RI.p07 = 62, 1, 0)
     + IF(RI.p08 = 98, 1, 0)
     + IF(RI.p09 = 14, 1, 0)
     + IF(RI.p10 = 25, 1, 0)
     + IF(RI.p11 = 34, 1, 0)
     + IF(RI.p12 = 67, 1, 0)
     + IF(RI.p13 = 81, 1, 0)
     + IF(RI.p14 = 29, 1, 0)
     + IF(RI.p15 = 24, 1, 0)
     + IF(RI.p16 = 45, 1, 0)
     + IF(RI.p17 = 72, 1, 0)
     + IF(RI.p18 = 86, 1, 0)
     + IF(RI.p19 = 25, 1, 0)
     + IF(RI.p20 = 95, 1, 0)
     + IF(RI.p21 = 92, 1, 0)
     + IF(RI.p22 = 31, 1, 0)
     + IF(RI.p23 = 24, 1, 0)
     + IF(RI.p24 = 78, 1, 0)) AS ATTP
FROM RP
LEFT JOIN RI
    ON RP.rID = RI.rID
    AND RP.nID = '1'
WHERE RI.p25 > ((RI.p27 + RI.p26) * 8)
ORDER BY ATTP DESC LIMIT 1000000;

在实际情况下,有27种此类假设,并且查询需要25-35秒才能完成。

我检查这些条件的表是相关的,并且每天增长约50000条记录。

为加快查询的速度,我在iNR上具有主索引, 但是如何加快这些IFS的速度?

执行计划:

enter image description here

表结构:

CREATE TABLE `RI` (
  `rID` mediumint(5) unsigned NOT NULL AUTO_INCREMENT,
  `p01` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p02` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p03` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p04` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p05` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p06` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p07` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p08` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p09` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p10` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p11` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p12` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p13` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p14` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p15` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p16` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p17` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p18` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p19` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p20` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p21` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p22` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p23` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p24` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p25` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p26` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `p27` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `ils` mediumblob NOT NULL,
  PRIMARY KEY (`rID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_lithuanian_ci;

CREATE TABLE `RP` (
  `pID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `rID` mediumint(8) unsigned NOT NULL,
  `nID` mediumint(8) unsigned NOT NULL,
  PRIMARY KEY (`pID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_lithuanian_ci;

2 个答案:

答案 0 :(得分:1)

修复1 :对a,b,c和d的所有4列建立索引将有助于更快地处理。

修复2 :可能添加了一个触发器,当插入或更新值时,该触发器将更新同一表中的另一列将解决该问题。

这两个修复都是临时性修复,请提供有关问题陈述的更多信息,说明为什么需要查询if 希望对您有帮助

答案 1 :(得分:1)

现在,当我们获得真正的查询和DDL时,它可以非常轻松地为您提供帮助! :)

尝试创建以下索引:

CREATE INDEX IX_RP_nID_rID ON RP (nID, rID);

这应该消除现在正在进行的完整RP表扫描。它应该会大大增强性能,但仍有改进的空间。

此外,我认为您的LEFT JOIN的行为与INNER JOIN相同,因为您在WHERE子句中仍有过滤条件。

我看到InnoDB让您索引表达式。如果您总是查询完全相同的列,则可以尝试在RI表上创建一个索引,该索引将在select语句中包含rID,p25((p27 + p.26)* 8)和整个表达式。从技术上讲,这应该坚持计算。

但是此解决方案将在mysql更新https://dev.mysql.com/doc/refman/8.0/en/create-index.html

之后使用