【发布时间】:2020-07-24 03:00:25
【问题描述】:
解释上下文。在工作中,我们正在运行一个使用 MySQL 作为数据缓存的 Java 应用程序。 我们正在运行一些缓慢的蒙特卡罗过程以获得一些结果。 然后我们将它们插入数据库以供以后使用,这样我们就不需要为相同的配置再次执行昂贵的蒙特卡罗。
这里是建表代码:
CREATE TABLE `cache_lte_perfbe_saved` (
`CNUMZONE` DECIMAL(10,5) NOT NULL,
`IDDATASET` INT(11) NOT NULL,
`CRB` INT(11) NOT NULL,
`CENVIRONMENT` VARCHAR(45) NOT NULL,
`CPROPAGATION` VARCHAR(45) NOT NULL,
`CSECTORCONF` VARCHAR(60) NOT NULL,
`CFREQUENCY` INT(11) NOT NULL,
`CINTERCELLLOAD` INT(11) NOT NULL,
`CNBST` INT(11) NOT NULL,
`CNBBE` INT(11) NOT NULL,
`IDLTECONF` INT(11) NOT NULL,
`CTHROUGHPUT` VARCHAR(50) NOT NULL,
`CTHROUGHPUT_ARITHMETIC` DECIMAL(9,2) NOT NULL,
`CDISTRIB` DECIMAL(12,10) NOT NULL,
`VOLTETRAFFICGB` VARCHAR(50) NOT NULL,
`PID` VARCHAR(45) NOT NULL DEFAULT '0',
`SERVICENAME` VARCHAR(50) NOT NULL,
`VOLTETRAFFICERL` VARCHAR(50) NOT NULL,
PRIMARY KEY (`IDDATASET`, `CRB`, `CNBST`, `CNBBE`, `IDLTECONF`, `CNUMZONE`, `CENVIRONMENT`, `CPROPAGATION`, `CFREQUENCY`, `CINTERCELLLOAD`, `SERVICENAME`, `PID`, `VOLTETRAFFICGB`, `VOLTETRAFFICERL`, `CSECTORCONF`) USING HASH,
INDEX `PK_noVoltenoSectorConf` (`IDDATASET`, `CRB`, `CENVIRONMENT`, `CPROPAGATION`, `CFREQUENCY`, `CINTERCELLLOAD`, `CNBST`, `CNBBE`, `IDLTECONF`, `PID`) USING HASH,
INDEX `PK_noVoLTE` (`IDDATASET`, `CRB`, `CENVIRONMENT`, `CPROPAGATION`, `CSECTORCONF`, `CFREQUENCY`, `CINTERCELLLOAD`, `CNBST`, `CNBBE`, `IDLTECONF`, `PID`) USING HASH,
INDEX `PK_noVoLTEnoFrequency` (`IDDATASET`, `CRB`, `CENVIRONMENT`, `CPROPAGATION`, `CSECTORCONF`, `CNBST`, `CNBBE`, `PID`, `IDLTECONF`) USING HASH)COLLATE='utf8_general_ci' ENGINE=InnoDB ;
这是一个大约需要 3 秒的查询:
SELECT *
FROM cache_lte_perfbe_saved
WHERE IDDATASET = 6
AND CRB = 100
AND CENVIRONMENT = 'high'
AND CPROPAGATION = 'IndDay'
AND CFREQUENCY = 1800
AND CINTERCELLLOAD = 82.0
AND CNBST >= 0
AND CNBST <= 0
AND CNBBE <= 30
AND PID = 1586536071412
AND IDLTECONF IN ( 2, 17, 18 )
AND VOLTETRAFFICERL = 40.0
UNION
SELECT *
FROM cache_lte_perfbe
WHERE IDDATASET = 6
AND CRB = 100
AND CENVIRONMENT = 'high'
AND CPROPAGATION = 'IndDay'
AND CFREQUENCY = 2600
AND CINTERCELLLOAD = 88.0
AND CNBST >= 0
AND CNBST <= 0
AND CNBBE <= 30
AND PID = 1586536071412
AND IDLTECONF IN ( 2, 17, 18 )
AND VOLTETRAFFICERL = 40.0
UNION
SELECT *
FROM cache_lte_perfbe
WHERE IDDATASET = 6
AND CRB = 50
AND CENVIRONMENT = 'high'
AND CPROPAGATION = 'IndDay'
AND CFREQUENCY = 800
AND CINTERCELLLOAD = 84.0
AND CNBST >= 0
AND CNBST <= 0
AND CNBBE <= 30
AND PID = 1586536071412
AND IDLTECONF IN ( 2, 17, 18 )
AND VOLTETRAFFICERL = 40.0
[/代码]
这里是这个查询的解释结果: click
查询返回 3000 行。
就目前而言,我们可以插入 200 万行,这将使查询变得非常慢。 我有多个索引,因为我们需要根据模拟选项查询不同的东西。这意味着我们不会总是使用主键中的所有列,因此索引将毫无用处。
你能帮我优化这个查询吗?我正在考虑是否应该为每种情况使用不同的表格。也许使用Mysql作为缓存不是一个好主意..也许我应该尝试在内存中制作这张表?
让我知道你的想法。 干杯!
【问题讨论】:
-
您在 EXPLAIN 中列出的第一个键长度为 302 的表阻碍了典型性能,并且使表中悬挂的三个索引膨胀。
-
如果所有辅助列都已在 PK 中,则不会膨胀。
-
VOLTETRAFFICERL= 40.0 看起来是数字,但声明为VARCHAR。CINTERCELLLOAD有小数点,但声明为INT?? -
@RickJames 很好地观察了这个流量,我已经把它变成了十进制的 10,2。