在同步查询的情况下对MySQL RDS性能的挑战
我有一个通过AWS上的NodeJS开发的应用程序,该应用程序与MySQL RDS数据库(服务器类:db.r3.large – Engine:InnoDB)相关联。 我们遇到性能问题,当我们同时执行同时查询时,数据库在完成最后一个查询后返回结果,而不是在每个查询完成后返回结果。
所以,举个例子:如果我们执行一个有10个同时查询的进程,每个查询的时间间隔为3秒,我们开始接收结果的时间约为30秒,我们希望在第一个查询完成(3秒)时开始接收数据。
看来,数据库正在接收查询并对其进行排队。
我有点迷失在这里,因为我改变了代码和AWS的几个东西(单独的连接,池连接等),但似乎并没有改善结果。
表A(13Mlogging)架构:
CREATE TABLE `TableA` ( `columnA` int(11) NOT NULL AUTO_INCREMENT, `columnB` varchar(20) DEFAULT NULL, `columnC` varchar(15) DEFAULT NULL, `columnD` varchar(20) DEFAULT NULL, `columnE` varchar(255) DEFAULT NULL, `columnF` varchar(255) DEFAULT NULL, `columnG` varchar(255) DEFAULT NULL, `columnH` varchar(10) DEFAULT NULL, `columnI` bigint(11) DEFAULT NULL, `columnJ` bigint(11) DEFAULT NULL, `columnK` varchar(5) DEFAULT NULL, `columnL` varchar(50) DEFAULT NULL, `columnM` varchar(20) DEFAULT NULL, `columnN` int(1) DEFAULT NULL, `columnO` int(1) DEFAULT '0', `columnP` datetime NOT NULL, `columnQ` datetime NOT NULL, PRIMARY KEY (`columnA`), KEY `columnB` (`columnB`), KEY `columnO` (`columnO`), KEY `columnK` (`columnK`), KEY `columnN` (`columnN`), FULLTEXT KEY `columnE` (`columnE`) ) ENGINE=InnoDB AUTO_INCREMENT=13867504 DEFAULT CHARSET=utf8;
表B(15Mlogging)架构:
CREATE TABLE `TableB` ( `columnA` int(11) NOT NULL AUTO_INCREMENT, `columnB` varchar(50) DEFAULT NULL, `columnC` varchar(50) DEFAULT NULL, `columnD` int(1) DEFAULT NULL, `columnE` datetime NOT NULL, `columnF` datetime NOT NULL, PRIMARY KEY (`columnA`), KEY `columnB` (`columnB`), KEY `columnC` (`columnC`) ) ENGINE=InnoDB AUTO_INCREMENT=19153275 DEFAULT CHARSET=utf8;
查询:
SELECT COUNT(*) AS total FROM TableA WHERE TableA.columnB IN ( SELECT TableB.columnC FROM TableB WHERE TableB.columnB = "3764301" AND TableB.columnC NOT IN ( SELECT field FROM table WHERE table.field = 10 AND TableB.columnC NOT IN ( SELECT field FROM table WHERE table.field = 10 AND TableB.columnC NOT IN ( SELECT field FROM table WHERE table.field = 10 AND TableB.columnC NOT IN ( SELECT field FROM table WHERE table.field = 10 ) AND columnM > 2;
- 1秒内执行返回
- 10次执行会在20秒内返回第一个结果,在此之后返回另一个结果。
要查看查询正在运行,我正在使用“SHOW FULL PROCESSLIST”,查询大部分时间都是状态“发送数据”。
这不是关于查询的性能问题,而是数据库重复发生的问题。 即使是一个非常简单的查询,如“SELECT COUNT(*)FROM TableA WHERE columnM = 5”也有同样的问题。
UPDATE
仅用于testing目的,我减less查询只有一个子查询条件。 两项结果都有65k的logging。
-- USING IN SELECT COUNT(*) as total FROM TableA WHERE TableA.columnB IN ( SELECT TableB.columnC FROM TableB WHERE TableB.columnB = "103550181" AND TableB.columnC NOT IN ( SELECT field FROM tableX WHERE fieldX = 15 ) ) AND columnM > 2; -- USING EXISTS SELECT COUNT(*) as total FROM TableA WHERE EXISTS ( SELECT * FROM TableB WHERE TableB.columnB = "103550181" AND TableA.columnB = TableB.columnC AND NOT EXISTS ( SELECT * FROM tableX WHERE fieldX = 15 AND fieldY = TableB.columnC ) ) AND columnM > 2; -- Result Query using IN : 1.7 sec Query using EXISTS : 141 sec (:O)
使用IN或EXISTS的问题是一样的,当我执行多次这个查询时,数据库会有一个延迟,而且响应时间很长。 例如:如果一个查询响应在1.7秒内,如果我执行10次这个查询,第一个结果是20秒。
build议1
将NOT IN ( SELECT ... )
更改为NOT EXISTS ( SELECT * ... )
。 (您可能需要稍微更改WHERE
子句。
AND TableB.columnC NOT IN ( SELECT field FROM table WHERE table.field = 10
– >
AND NOT EXISTS ( SELECT * FROM table WHERE field = TableB.columnC )
table
需要一个field
的索引。
IN ( SELECT ... )
performance很差。 EXISTS
更好的优化。
build议2
要处理并发性,请考虑在查询之前执行SET SESSION TRANSACTION READ UNCOMMITTED
。 这可以保持一个连接不干扰另一个连接。
build议3
向我们展示EXPLAIN
,索引( SHOW CREATE TABLE
)(你给的东西是不够的),和WHERE
子句,这样我们可以批评索引。
build议4
这可能会有助于TableB
具有一个复合INDEX(ColumnB, ColumnC)
的顺序。
我可以在这里看到的是巨大的临时表正在为每个查询构build。 考虑不同的架构。