我正在使用和使用MySQL作为后端引擎的软件(它可以使用其他如PostgreSQL或Oracle或SQLite,但这是我们正在使用的主要应用程序)。该软件的设计方式使我们要访问的二进制数据在各列中保存为 BLOB (每个表有一个 BLOB 列,其他列有整数/浮点数表征 BLOB ,以及一个带有 BLOB 的MD5哈希的字符串列。这些表通常有2,3或4个索引,其中一个始终是MD5列,它是UNIQUE
。有些表已经有数百万个条目,并且它们已经输入了数千兆字节的大小。我们在同一台服务器中保留了每年独立的MySQL数据库(到目前为止)。对于一般应用程序(Dell PowerEdge 2U格式服务器),硬件非常合理(我认为)。
MySQL SELECT
查询相对较快。那里几乎没有抱怨,因为这些是(大部分时间)处于批处理模式。但是,INSERT
查询需要很长时间,这会随表大小(行数)而增加。不可否认,这是因为MD5列的类型为UNIQUE
,因此每个INSERT
必须确定每个新行是否具有相应的,已插入的MD5字符串。如果有其他索引(不是唯一的),如果性能变差,那就不奇怪了(我认为)。但是我仍然无法放下这个软件架构选择(我怀疑 BLOBs 在表行而不是磁盘中具有显着的负面影响)并不是最好的选择。插入并不重要,但这是一种令人讨厌的感觉。
有没有人有类似情况的经验?使用MySQL,甚至是其他(最好是基于Linux的)RDBM?你想提供的任何见解,也许是一些表现数据?
BTW,工作语言是C ++(它包含对MySQL API的C调用)。答案 0 :(得分:10)
可能是水平分区并将blob字段移动到单独的表中的时间。在这篇关于“垂直分区的快速侧注”的article中,作者从表中删除了一个更大的varchar字段,它提高了查询的速度。
原因是如果要覆盖的空间较少,磁盘上数据的物理遍历会变得非常快,因此在其他地方移动更大的字段会提高性能。
另外(你可能已经这样做了)将索引列的大小减小到绝对最小值(在md5的ascii编码中为char(32))是有益的,因为键的大小与速度成正比它的用途。
如果您使用InnoDB表一次执行多次插入,则可以通过将插入包装到事务中并在一个查询中执行mupliple插入来显着提高插入速度:
START TRANSACTION
INSERT INTO x (id, md5, field1, field2) values (1, '123dab...', 'data1','data2'),(2,'ab2...','data3','data4'),.....;
COMMIT
答案 1 :(得分:5)
见Speed of INSERT Statements。你经常碰到MD5吗?我相信这些不应该发生太多次,所以也许你可以使用类似INSERT ... ON DUPLICATE的东西来处理碰撞。如果您有特定的插入期间,则可以disable keys插入时间并稍后恢复。另一种选择是使用replication,使用主机进行插入,使用从机进行选择。
答案 2 :(得分:1)
您使用的是MyISAM吗? AFAIK MyISAM具有非常好的读取性能,但写入性能不佳。
InnoDB应该在速度上保持平衡。
答案 3 :(得分:1)
您的数据是否适合RAM?如果没有,请获得更多的RAM,直到变得不经济(16G通常是大多数人的关键)。
然后,您的索引是否适合MyISAM密钥缓冲区?
如果您运行的是32位操作系统,请不要这样做。一旦使用64位操作系统,将密钥缓冲区设置为大约1/3的RAM。操作系统的缓存使用RAM来缓存数据文件(这对插入很少,但对选择很有用)。
在MyISAM中使用数GB表可能会很痛苦,因为如果发生不干净的关机,则需要非常冗长的维修操作,但
如果没有对应用程序进行重要验证,请不要切换MySQL引擎,它会以多种方式改变行为(而不仅仅是性能)。它会影响磁盘空间的使用。
答案 4 :(得分:1)
我今天也问了一些与此有关的question。
提供的答案之一是考虑INSERT DELAYED
以便它进入插入队列,并在数据库不忙时处理。