infobright是基于mysql的列存储数据仓库解决方案
Infobright框架图
如上图所示,Infobright采用了和MySQL一致的构架,分为两层。
上层是服务及应用管理,下层是存储引擎。
Infobright的默认存储引擎是brighthouse,但是Infobright还可以支持其他的存储引擎,比如MyISAM、MRG_MyISAM、Memory、CSV。
infobright ice版本中不允许对brighthouse引擎进行写入,对于其他引擎没有限制。

这意味着我们可以灵活运用ice版本,一般数据级别的表、需要频繁进行写操作的表使用myisam引擎存储,特别巨大的数据表、以读为主数据表使用brighthouse引擎存储。

mysql> insert into a values ('1');
ERROR 1031 (HY000): Table storage engine for 'a' doesn't have this option
mysql> insert into c values ('1');
Query OK, 1 row affected (0.08 sec)

表a是brighthouse引擎,表c是myisam引擎。

infobright的导入

ice版brighthouse引擎的写入方式只能是load data

infobright ice使用手册的第36页列举了一些import时可能遇到的报错和处理方法,但是比较笼统。
结合个人在实验中遇到的一些问题,简单说明一下:

一、load data时一定要指定分隔符,这与myisam、innodb load data infile 时默认字段(列)分隔符是 \t不同

如果不指定分隔符会抛出以下错误:
mysql> load data local infile '/data/111.txt' into table a;

ERROR 5 (HY000): Unable to detect the line terminating sequence, please specify it explicitly.

mysql> load data local infile '/data/111.txt' into table a fields terminated by '\t';

Query OK, 9 rows affected (0.12 sec)

Records: 9  Deleted: 0  Skipped: 0  Warnings: 0

二、字段中的特殊字符和字符集
1、如果数据库与表的字符集不统一,导入数据时会抛出
infobright :ERROR 2 (HY000) at line 1: Wrong data or column definition. Row: 39075, field: 2
关于mysql字符集和校对规则这里不多赘述,目前我们常用的字符集utf8在infobright中被全面支持,详见infobright ice使用手册的第30页
所以字符集一定统一使用utf8

2、某些特殊fields不会转义,即使你escaped by '\\'
这个问题同样会抛出infobright :ERROR 2 (HY000) at line 1: Wrong data or column definition. Row: 39075, field: 2
我在实际操作中发现 大于小于号正反斜杠 > < \ / 等等都会报错,没有更好的解决方法,只能与研发共同制定规则在使用brighthouse引擎的表中尽量不使用特殊字符


infobright的导出

导出有两种方法:select into和mysqldump,这基本与mysql的使用一致
但是使用mysqldump时需要注意 要加上single-transaction选项,否则会抛出:
mysqldump: Got error: 1031: Table storage engine for 'BRIGHTHOUSE' doesn't have this option when using LOCK TABLES
因为brighthouse引擎使用列存储方式,不支持锁定。


brighthouse的文件系统和压缩方式

以同样一张300多万的表做实验,关于brighthouse引擎的压缩介绍在手册的第26~28页

myisam:
-rw-rw---- 1 mysql mysql 180M Feb 27 13:41 loginlog_201203.MYD
-rw-rw---- 1 mysql mysql 123M Feb 28 03:00 loginlog_201203.MYI

innodb(row_format=compressed):
-rw-rw---- 1 mysql mysql 8.6K Mar  6 10:32 ddd.frm
-rw-rw---- 1 mysql mysql 332M Mar  6 10:38 ddd.ibd

brighthouse:
21M     ./loginlog_201203.bht


myisam数据文件+索引文件为303m
innodb压缩模式下为332m
brighthouse所有文件一共21m

show full columns命令可以看到表每一列的信息,包括大小和压缩比

mysql> show full columns from loginlog_2012031;
wKioL1NMx6PDxhsdAAHZ81btU-Y420.jpg

也可以在文件系统下查看表的物理文件,可以看到brighthouse引擎以列为单位进行存储:
[root@dev_cvs loginlog_2012031.bht]# ll -h
total 21M
-rw-rw---- 1 mysql mysql 4.4K Feb 27 13:42 TA00000000000001.ctb
-rw-rw---- 1 mysql mysql  117 Feb 27 13:42 TA00000.ctb
-rw-rw---- 1 mysql mysql 1.9K Feb 27 13:42 TA00000DPN.ctb
-rw-rw---- 1 mysql mysql  12M Feb 27 13:42 TA00001000000001.ctb       //username列的数据块
-rw-rw---- 1 mysql mysql  107 Feb 27 13:42 TA00001.ctb
-rw-rw---- 1 mysql mysql 1.9K Feb 27 13:42 TA00001DPN.ctb                  //username列的数据块节点
-rw-rw---- 1 mysql mysql 666K Feb 27 13:42 TA00002000000001.ctb
-rw-rw---- 1 mysql mysql  124 Feb 27 13:42 TA00002.ctb
-rw-rw---- 1 mysql mysql 1.9K Feb 27 13:42 TA00002DPN.ctb
-rw-rw---- 1 mysql mysql 7.6M Feb 27 13:42 TA00003000000001.ctb
-rw-rw---- 1 mysql mysql  106 Feb 27 13:42 TA00003.ctb
-rw-rw---- 1 mysql mysql 1.9K Feb 27 13:42 TA00003DPN.ctb
-rw-rw---- 1 mysql mysql 3.1K Feb 27 13:42 TA00004000000001.ctb
-rw-rw---- 1 mysql mysql  119 Feb 27 13:42 TA00004.ctb
-rw-rw---- 1 mysql mysql 1.9K Feb 27 13:42 TA00004DPN.ctb
-rw-rw---- 1 mysql mysql   66 Feb 27 13:35 Table.ctb
-rw-rw---- 1 mysql mysql  117 Feb 27 13:35 TB00000.ctb
-rw-rw---- 1 mysql mysql  107 Feb 27 13:35 TB00001.ctb
-rw-rw---- 1 mysql mysql  124 Feb 27 13:35 TB00002.ctb
-rw-rw---- 1 mysql mysql  106 Feb 27 13:35 TB00003.ctb
-rw-rw---- 1 mysql mysql  119 Feb 27 13:35 TB00004.ctb

根据手册提供计算方式,varchar字段的原始大小 = 该列的字符串总长度 + (2 * 行数)
wKiom1NMx96SvFntAAKtziHSOyM966.jpg
我们拿username这一列来看:
mysql> select sum(length(username)) from loginlog_2012031;
+-----------------------+
| sum(length(username)) |
+-----------------------+
|              65878877 |
+-----------------------+
mysql> select count(*) from loginlog_2012031;
+----------+
| count(*) |
+----------+
|  3229127 |
+----------+

该列字符串总长度为65878877,行数为3229127

65878877+(2*3229127)=72337131 bytes

72337131/1024/1024 = 68 mb

与表信息中的size和Ratio计算出的值11.7mb*5.35=63mb基本符合


infobright的性能

通过以上的一些实验,我们已经发现brighthouse引擎具有很好的压缩比率。

Infobright通过三层来组织数据,分别是DP(Data Pack)、DPN(Data Pack Node)、KN(Knowledge Node)。
而在这三层之上就是无比强大的知识网络(Knowledge Grid)。    
数据块(DP)是存储的最低层,列中每64K个单元组成一个DP。DP比列更小,具有更好的压缩比率;又比单个数据单元更大,具有更好的查询性能。    
数据块节点(DPN),DPN和DP之间是一对一的关系。DPN记录着每一个DP里面存储和压缩的一些统计数据,包括最大值、最小值、null的个数、单元总数count、sum等等。
KN里面存储着指向DP之间或者列之间关系的一些元数据集合,比如值发生的范围(MIin_Max)、列数据之间的关联。大部分的KN数据是装载数据的时候产生的,另外一些事是查询的时候产生。    

在这三层之上是知识网络(Knowledge Grid),Knowledge Grid构架是Infobright高性能的重要原因。

以下是对一张17000000行数据表分别使用innodb、myisam、brighthouse引擎的查询实验,brighthouse的性能优势显而易见:
innodb
mysql> select sum(log_id),posttime from items group by posttime order by sum(log_id) limit 5;
+-------------+------------+
| sum(log_id) | posttime   |
+-------------+------------+
|    79396094 | 1389110455 |
|    79396285 | 1389110490 |
|    79396317 | 1389110498 |
|    79398821 | 1389110624 |
|    79419034 | 1389111848 |
+-------------+------------+
5 rows in set (55.93 sec)

myisam
mysql> select sum(log_id),posttime from items_1 group by posttime order by sum(log_id) limit 5;
+-------------+------------+
| sum(log_id) | posttime   |
+-------------+------------+
|    79396094 | 1389110455 |
|    79396285 | 1389110490 |
|    79396317 | 1389110498 |
|    79398821 | 1389110624 |
|    79419034 | 1389111848 |
+-------------+------------+
5 rows in set (50.09 sec)

brighthouse
mysql> select sum(log_id),posttime from items_2 group by posttime order by sum(log_id) limit 5;
+-------------+------------+
| sum(log_id) | posttime   |
+-------------+------------+
|    79396094 | 1389110455 |
|    79396285 | 1389110490 |
|    79396317 | 1389110498 |
|    79398821 | 1389110624 |
|    79419034 | 1389111848 |
+-------------+------------+
5 rows in set (5.92 sec)


Infobright comment lookup使用

对于值域范围不大的字段,infobright提供了压缩方式和性能表现更好的lookup字段,在储存状态、性别这类字段时非常有用。
但是对于值域范围在10000以上的字段不推荐使用,性能表现会变差。详见ice手册23页

还是用items表实验,将channel字段和posttime字段设为lookup
channel的值域较小,postime值域较大

不设lookup:
mysql> select count(distinct channel) from items_2;
+-------------------------+
| count(distinct channel) |
+-------------------------+
|                      93 |
+-------------------------+
1 row in set (24.83 sec)

设为lookup:
mysql> select count(distinct channel) from items_lookup;
+-------------------------+
| count(distinct channel) |
+-------------------------+
|                      93 |
+-------------------------+
1 row in set (10.05 sec)

在值域较小的channel上,加了lookup的查询速度要快一倍。


不设lookup:
mysql> select sum(log_id),channel from items_2 group by posttime order by sum(log_id) limit 5;
+-------------+-------------------+
| sum(log_id) | channel           |
+-------------+-------------------+
|    79396094 | system_send       |
|    79396285 | system_send       |
|    79396317 | system_send       |
|    79398821 | system_send       |
|    79419034 | combat_quest_drop |
+-------------+-------------------+
5 rows in set (8.83 sec)

设为lookup:
mysql> select sum(log_id),channel from items_lookup group by posttime order by sum(log_id) limit 5;
+-------------+-------------------+
| sum(log_id) | channel           |
+-------------+-------------------+
|    79396094 | system_send       |
|    79396285 | system_send       |
|    79396317 | system_send       |
|    79398821 | system_send       |
|    79419034 | combat_quest_drop |
+-------------+-------------------+
5 rows in set (9.62 sec)

在值域较大的posttime上加了lookup,并以posttime作为group by条件,查询速度反而比不加慢了。


infobright的日志

错误日志和常规日志详见ice手册第17页

这里主要讲一下二进制日志

在配置文件中加入二进制日志选项,可以正常启动服务,但是开启后发现statment\row\mixed模式下都无法load数据了(三种模式都试过了)

mysql> load data infile '/usr/local/mysql/data/111.txt' into table d fields terminated by '\t';
ERROR 1598 (HY000): Binary logging not possible. Message: Statement cannot be logged to the binary log in row-based nor statement-based format

这是不是意味着ice版本不能用二进制日志,也无法使用replication等高可用方案了?
这是我使用中的一个疑问。