我目前正在处理财务申请。一个包含8列的MYSql数据库。 1百万条记录。
插入:每分钟30行 更新:0。
选择:一个查询 每200ms运行一次。返回大约200,000条记录 每次执行。
选择查询,如下所示:
SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE FROM TABLE
WHERE COLUMNE IN('ABCD','EFGH','IJKL','MNOP')
ORDER BY COLUMNB DESC
我的回复时间如下:执行:0.903秒获取:0.2秒。
总计~1.1秒
当我做一个解释时,我得到以下内容:
id,select_type,table,partitions,type,possible_keys,key,key_len, ref,rows,filtered,Extra'1','SIMPLE','table',NULL,'ALL', 'tbl_ColumnE_ColumnB,tbl_ColumnE',NULL,NULL, NULL,'1180834','34 .33','使用where;使用filesort'
INDEXES已经有效:
因为这是一个基于金融股票市场的应用程序。我需要将总执行时间进一步降低到接近200毫秒或尽可能小。有什么我可以改进的吗?
已经完成:
显示创建表:
CREATE TABLE `tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`COLUMNB` timestamp NULL DEFAULT NULL,
`COLUMNC` decimal(20,10) DEFAULT NULL,
`COLUMND` decimal(20,10) DEFAULT NULL,
`COLUMNX` decimal(20,10) DEFAULT NULL,
`COLUMNY` decimal(20,10) DEFAULT NULL,
`COLUMNZ` decimal(20,10) DEFAULT NULL,
`COLUMNE` varchar(45) DEFAULT NULL,
`COLUMNF` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `tbl_ColumnE_ColumnB` (`ColumnE`,`ColumnB`),
KEY `tbl_ColumnB_ColumnE` (`ColumnB`,`ColumnE`),
KEY `tbl_ColumnB` (`ColumnB`),
KEY `tbl_ColumnE` (`ColumnE`)
) ENGINE=InnoDB AUTO_INCREMENT=1718507 DEFAULT CHARSET=utf8'
答案 0 :(得分:0)
此查询:
SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE
FROM TABLE
WHERE COLUMNE IN ('ABCD', 'EFGH', 'IJKL', 'MNOP')
ORDER BY COLUMNB DESC;
没有方便的优化方法。问题是IN
和ORDER BY
。对于IN
列表中的单个值,最佳索引可能是(COLUMNE, COLUMNB, COLUMNC, COLUMND)
(在MySQL中降序排列可能很棘手)。
如果IN
列表中的四个值是常量,我建议更改数据结构,使它们在一列中。然后这个查询:
SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE
FROM TABLE
WHERE COLUMNEPRIME = 'ABCDEFGHIJKLMNOP'
ORDER BY COLUMNB DESC;
可以利用(COLUMNEPRIME, COLUMNB, COLUMNC, COLUMND, COLUMNE)
上的索引。唉,在MySQL中,可能需要使用一个会减慢插入速度的触发器。
如果获取速度如此之快,您可能会发现在应用程序而不是数据库中排序更快。因此,请尝试查询:
SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE
FROM TABLE
WHERE COLUMNE IN ('ABCD', 'EFGH', 'IJKL', 'MNOP');
使用四部分复合索引。
我注意到,对于大多数用途来说,每秒多次返回20%的表似乎是不必要的。也许有更好的方法来设计整个系统来做你需要的。
答案 1 :(得分:0)
试试这个。你在COLUMNE有多少种不同的数据?如果不是这样,你也可以使用ENUM来加速查询。 您还可以使用客户端中的compress选项来最小化数据传输。
CREATE TEMPORARY TABLE `tbls` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`val` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `val` (`val`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO tbls (val) VALUES('ABCD'),('EFGH'),('IJKL'),('MNOP');
EXPLAIN
SELECT COLUMNB, COLUMNC, COLUMND, COLUMNE FROM tbl
INNER JOIN tbls ON tbl.COLUMNE = tbls.val
ORDER BY COLUMNB DESC;
答案 2 :(得分:0)
与IN匹配的行的百分比是多少?如果它超过20%,优化器将避开索引(从E开始),因为扫描整个表可能会更快。
需要Sort(“filesort”),因为无法以正确的顺序获取行。您可以尝试FORCE INDEX(ColumnB)
。
查询花费这么长时间的部分原因是您返回200K行。思考你是否可以避免这种情况。
但等等!如果你每2秒只插入一行,为什么你觉得0.2秒后会有什么变化?当您插入一行时,触发重新计算(此连接必须在应用程序中完成,不能完全在sql中完成)。这将导致更快的响应,因为您不会在下一次计算时等待0.2秒。