mysql并行读写查询性能

dgjrabp2  于 2021-06-23  发布在  Mysql
关注(0)|答案(4)|浏览(354)

我有一个简单的表,有15列:

CREATE TABLE MYTABLE(
ID int(11) NOT NULL AUTO_INCREMENT,
SYMBOL varchar(100) NOT NULL,
DATE varchar(100) NOT NULL,
TIME varchar(100) NOT NULL,
NUMBER decimal(38,0) NOT NULL,
A float DEFAULT NULL,
B float DEFAULT NULL,
C float DEFAULT NULL,
D float DEFAULT NULL,
E decimal(38,0) DEFAULT NULL,
F float DEFAULT NULL,
G decimal(38,0) DEFAULT NULL,
H decimal(38,0) DEFAULT NULL,
I decimal(38,0) DEFAULT NULL,
J float DEFAULT NULL,
K float DEFAULT NULL,
L decimal(38,0) DEFAULT NULL,
M decimal(38,0) DEFAULT NULL,
MILLIS decimal(38,0) DEFAULT NULL,
PRIMARY KEY (ID)
KEY SYM (SYMBOL) USING HASH
) ENGINE=InnoDB AUTO_INCREMENT=10250241 DEFAULT CHARSET=latin1

它由符号索引(哈希索引)。这个数据表(6gb)中大约有10000000行。在workbench中查询此表时,对于以下简单查询:

select  *  from MYTABLE WHERE symbol = 'A' and date>= '2018-08-01' and 
date<= '2018-08-09' and time>= '09:24:00' and time <= '15:24:00' order by 
millis desc ;'

需要4-5秒。当对数据库的读写同时发生时,性能进一步降低。但这是一个实时数据库,要求从一个连接写入数据,从另一个连接读取数据。
有人能提出一些优化性能的方法吗。随着时间的推移,我已经尝试了btree索引,但性能进一步下降。
如前所述,在对查询运行explain之后,我得到了以下结果:

'Using index condition; Using where; Using filesort'

iq3niunx

iq3niunx1#

对于此查询:

select * 
from MYTABLE 
where symbol = 'A' and
      date >= '2018-08-01' and date <= '2018-08-09' and 
      time >= '09:24:00' and time <= '15:24:00'
order by millis desc ;

你想要索引吗 mytable(symbol, date, time) . 事实上 time 只有一个副本,所以索引覆盖 WHERE 条款。
包括 millis 没有帮助,因为在 order by .

ddarikpa

ddarikpa2#

用desc在符号和millis上创建索引。

j7dteeu8

j7dteeu83#

DECIMAL(38,0) 需要17个字节。你真的需要那个数据类型吗( FLOAT 需要4分钟, DOUBLE 需要8分钟, BIGINT (缩小6gb将有助于提高性能,尤其是在 innodb_buffer_pool_size 是小的。)
如果 millis 是毫秒,为什么是38位,不是3位?不管怎样, DATETIME(3) 提供数据+时间+毫秒,全部打包为7个字节。此外,你可以

ORDER BY datetime

从而考虑到 INDEX(symbol, datetime) 帮助解决问题 WHERE . (这不能用当前代码完成。)

date >= '2018-08-01' and date <= '2018-08-09' and 
  time >= '09:24:00' and time <= '15:24:00'

在这9天中的每一天过滤到白天。如果这真的是你想要的,那么没有一个索引能很好地工作。检查 <= --我理解日期的包容性,但我暂时质疑。
或者 INDEX(symbol, date) 或者 INDEX(symbol, time) 是有用的。没有比这更好的了(除非你能把日期和时间结合起来)。把这两个加起来。 HASH innodb中不存在索引;这个请求被悄悄地变成了 BTREE ,这对于“点查询”和“范围查询”差不多好,而且非常好。在您的查询中,“复合”btree查询(见上一段)要好得多。
请提供 EXPLAIN SELECT ... 所以我们可以进一步推断出发生了什么。
一切都不是 ID 真的可以选择吗?考虑使用 NOT NULL . 'Using index condition; Using where; Using filesort' --“文件排序”是不可避免的;接受现实吧。”使用索引条件(又名“icp”)是好的。

j8ag8udp

j8ag8udp4#

DATE varchar(100) NOT NULL,
TIME varchar(100) NOT NULL,

我会从使用 DATE() 以及 TIME() 类型而不是 varchar (或一个) DATETIME() )-或储存在 integer 作为 Unix Time . 在内部,它们将比字符串更有效。
例如,比较两个整数大约需要1个cpu周期。要比较字符串,一般来说,每个字符都必须在循环中进行比较(直到有差异为止),除非使用了特殊的优化。如果数据是unicode格式的,则必须对每个字符进行特殊查找。
整数也比日期/时间字符串表示法占用更少的空间(unix时间为4字节),并且长度不可变(即使日期的长度都相同,在内部它们也将被视为可变长度字符串,需要额外的“长度字段”)。
还可以按照其他地方的建议创建适当的索引。

select * from MYTABLE 
where symbol = 'A' and
      date >= '2018-08-01' and date <= '2018-08-09' and 
      time >= '09:24:00' and time <= '15:24:00'
order by millis desc ;

您确定要(只)在下订单吗 millis ,或者这只是一个测试?
对于上面的查询,忽略 millis ,理想情况下,记录将按以下顺序存储在磁盘上: symbol, datetime (millis?) . 这样,要返回的记录将在磁盘上以块的形式紧密地放在一起。否则,它们可能分布在整个表中,需要许多磁盘查找和(块)读取来检索所有记录。

相关问题