我正在思考最佳的方法来存储所有这些数据并在以后检索。我的第一个想法是使用像MySQL这样的关系型数据库管理系统。作为一个嵌入式C/C++程序员,我很少有处理如此大量数据集的经验。我曾在小数据集上尝试过它,但从未处理过如此大的数据量。我为两个表生成了以下模式,用于存储部分数据:
CREATE TABLE IF NOT EXISTS `HEADER_TABLE` (
`header_id` tinyint(3) unsigned NOT NULL auto_increment,
`sensor` varchar(10) NOT NULL,
`bytes` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`header_id`),
UNIQUE KEY `header_id_UNIQUE` (`header_id`),
UNIQUE KEY `sensor_UNIQUE` (`sensor`)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `RAW_DATA_TABLE` (
`internal_id` bigint(20) NOT NULL auto_increment,
`time_sec` bigint(20) unsigned NOT NULL,
`time_nsec` bigint(20) unsigned NOT NULL,
`transverse` bit(1) NOT NULL default b'0',
`data` varbinary(1080) NOT NULL,
PRIMARY KEY (`internal_id`,`time_sec`,`time_nsec`),
UNIQUE KEY `internal_id_UNIQUE` (`internal_id`),
KEY `time` (`time_sec`)
KEY `internal_id` (`internal_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `rel_RASTER_TABLE` (
`internal_id` bigint(20) NOT NULL auto_increment,
`raster_id` int(10) unsigned NOT NULL,
`time_sec` bigint(20) unsigned NOT NULL,
`time_nsec` bigint(20) unsigned NOT NULL,
`header_id` tinyint(3) unsigned NOT NULL,
`data_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`internal_id`, `raster_id`,`time_sec`,`time_nsec`),
KEY `raster_id` (`raster_id`),
KEY `time` (`time_sec`),
KEY `data` (`data_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
表头只包含10行,是静态的。它只告诉原始数据来自哪个传感器,以及该类型传感器输出的字节数。RAW_DATA_TABLE实质上存储原始轴承数据(一个360-1080字节的数组,表示每度最多三个样本)。rel_RASTER_TABLE保存RAW_DATA_TABLE的元数据,可能有多个联系人引用同一行原始数据。在rel_RASTER_TABLE中找到的data_id指向RAW_DATA_TABLE中某一行的internal_id,我这样做是为了减少需要写入的数量。
显然,正如您可能已经注意到的那样,我在从这个数据库中读取和删除时遇到了性能问题。我们软件的操作员可以看到实时数据,也可以进入重建模式并叠加过去的数据范围,例如过去一周。我们的后端日志服务器抓取历史记录行,并通过CORBA接口将它们发送到显示器。在所有这些内容发生的同时,我有一个工作线程,每次删除1000行超过30天的数据。这是为了防止会话运行时间超过30天,这种情况可能会发生。
我们目前实施的系统对于较小的数据集运作良好,但对于大型数据集则不然。我们的选择和删除语句可能需要花费超过2分钟才能返回结果。这完全破坏了我们实时消费者线程的性能。我怀疑我们没有正确设计模式,选择了错误的键,没有正确优化SQL查询,或者是两者的某个子集。除非其他操作运行时间过长,否则我们的写入不会受到影响。
以下是我们用来获取历史数据的一个SQL查询示例:
SELECT
rel_RASTER_TABLE.time_sec,
rel_RASTER_TABLE.time_nsec,
RAW_DATA_TABLE.transverse,
HEADER_TABLE.bytes,
RAW_DATA_TABLE.data
FROM
RASTER_DB.HEADER_TABLE,
RASTER_DB.RAW_DATA_TABLE,
RASTER_DB.rel_RASTER_TABLE
WHERE
rel_RASTER_TABLE.raster_id = 2952704 AND
rel_RASTER_TABLE.time_sec >= 1315849228 AND
rel_RASTER_TABLE.time_sec <= 1315935628 AND
rel_RASTER_TABLE.data_id = RAW_DATA_TABLE.internal_id AND
rel_RASTER_TABLE.header_id = HEADER_TABLE.header_id;
我很抱歉这是一个如此冗长的问题,但我已经尽力寻找其他资源,这是我的最后一招。我想尽可能详细地描述。你们看到有什么方法可以在第一时间改进我们的设计吗?或者,我们有没有办法为如此大的数据集优化我们的选择和删除语句?我们目前正在运行RHEL作为操作系统,不幸的是不能更改服务器的硬件配置(4 GB RAM,四核)。我们正在使用C/C++和MySQL API。任何速度上的提升都将非常有益。如果您需要我澄清任何事情,请让我知道。谢谢!
编辑:顺便说一句,如果您无法提供具体帮助,也许您可以链接一些优秀的教程,用于优化SQL查询、模式设计或MySQL调整?