我正在开发基于 MySql 数据库的 PyQT 软件。该数据库包含一些记录的电信号,以及描述这些信号的所有信息(采样率、重新编码的日期等......)。
想一想,一个数据库包含 10 000 到 100 000 行,总大小 > 10Gb。所有这些数据都存储在专用服务器上。事实上,大部分数据是信号本身,它在一个名为analogsignal.signal的BLOB字段中(见下文)
这是数据库的架构:http ://packages.python.org/OpenElectrophy/_images/simple_diagram1.png
我无法更改它(我可以添加列和索引,但我无法移动或删除现有列)。
在软件中,我需要列出所有的模拟信号列(id、名称、通道、t_start、sampling_rate),除了analogsignal.signal,稍后通过analogsignal.id 调用。所以我正在做以下查询
选择 block.id、block.datetime、segment.id、analogsignal.id、analogsignal.name、analogsignal.channel、analogsignal.sampling_rate、block.fileOrigin、block.info
FROM 段、块、模拟信号
WHERE block.id=segment.id_block
AND segment.id=analogsignal.id_segment
由类比信号.id 订购
问题是,由于analogsignal.signal 列的存在,我的查询非常慢(如果请求不在缓存中,则> 10 分钟)。如果我正确理解发生了什么,表格会逐行读取,包括analogsignal.signal,即使analogsignal.signal 不在SELECT 字段中。
有谁知道如何在不将 BLOB 移动到其他表中的情况下优化数据库或查询(我同意这更合乎逻辑,但我不控制这一点)。
谢谢!
这是 AnalogSignal 表的 CREATE TABLE 命令(从评论中提取/格式化)
CREATE TABLE analogsignal
( id int(11) NOT NULL AUTO_INCREMENT,
id_segment int(11) DEFAULT NULL,
id_recordingpoint int(11) DEFAULT NULL,
name text,
channel int(11) DEFAULT NULL,
t_start float DEFAULT NULL,
sampling_rate float DEFAULT NULL,
signal_shape varchar(128) DEFAULT NULL,
signal_dtype varchar(128) DEFAULT NULL,
signal_blob longblob, Tag text,
PRIMARY KEY (id),
KEY ix_analogsignal_id_recordingpoint (id_recordingpoint),
KEY ix_analogsignal_id_segment (id_segment)
) ENGINE=MyISAM AUTO_INCREMENT=34798 DEFAULT CHARSET=latin1 ;
编辑:问题解决了,这里是关键点:
-我必须添加一个多列索引,在模拟信号表中的所有 SELECT 字段上键入 INDEX
-“TEXT”类型的列阻止了索引的使用。我在 VARCHAR(xx) 中转换了这些 TEXT 字段。为此,我使用了这个简单的命令:
从 table_to_query 中选择 MAX(LENGTH(field_to_query))
在转换之前检查最小文本长度,以确保我不会丢失任何数据
ALTER TABLE table_to_query CHANGE field_to_query field_to_query VARCHAR(24)
我第一次使用了 VARCHAR(8000),但是在这个设置下,VARCHAR 就像一个 TEXT 字段,并且索引不起作用。VARCHAR(24) 没有这样的问题。如果我是对的,则查询中的总 TEXT 长度(包括所有字段)不得超过 1000 个字节
然后我如上所述索引了所有列,索引中没有大小参数
最后,使用更好的查询结构(感谢 DRapp),也改进了查询。我从 215s 传递到 0.016s 的查询,没有缓存......