到目前为止,已经学习了表结构的字段类型选择和表的物理存储设计,这一节继续学习表的访问选型。字段类型选择+物理存储设计+表的访问设计,就完成了表结构设计的所有内容。
之前所讲都是通过SQL的方式对表进行访问,从MySQL 5.6 版本开始,就支持除SQL外的其他访问方式,比如NoSQL,甚至可以把MySQL打造成一个百万级并发访问的KV数据库或文档数据库。
MySQL中表的访问方式
SQL是访问数据库的一个通用接口,虽然数据库有很多种,但数据库中的SQL却是类似的,因为SQL有标准存在,如SQL92、SQL2003等。
虽然有些数据库会扩展支持SQL标准外的语法,但90%的语法是兼容的,所以,不同数据库在SQL层面的学习成本是比较低的。从一种关系型数据库迁移到另一种关系型数据库,开发的迁移成本并不高。比如去IOE,将Oracle数据库迁移到MySQL数据库,SQL语言并不是难题。
MySQL 8.0 版本之前,不少程序员同学会吐槽MySQL对于SQL标准的支持程度。但是在当前MySQL 8.0版本下,MySQL对于SQL语言的支持已经越来越好,设置在某些方面超过了商业数据库Oracle。
SQL标准支持上图是专家评估的不同数据库对SQL的支持程度,MySQL8.0在这一块已经非常完善,尤其是对JSON_TABLE的支持功能。
通常来说,MySQL数据库用于OLTP的在线系统中,不用特别复杂的SQL语言支持。但MySQL 8.0完备的SQL支持意味着MySQL未来将逐渐补齐在OLAP业务方面的短板,让我们拭目以待。
通过NoSQL的方式访问表中数据
MySQL中表的访问方式除了标准的SQL访问,MySQL 5.6版本开始支持通过Memcached通信协议访问表中的数据,这时MySQL可以作为一个KV数据库使用。
MySQL 5.7版本开始支持通过新的MySQL X 通信协议访问表中的数据,这时MySQL可以作为一个文档数据库使用。
但无论哪种NoSQL的访问方式,其访问的数据都是以表的方式进行存储,SQL和NoSQL之间通过某种映射关系进行绑定。
对比传统的NoSQL数据库(比如Memcached、MongoDB),MySQL这样的访问更具有灵活性,在通过简单的NoSQL接口保障性能的前提下又可以通过SQL的方式丰富对于数据的查询。另外,MySQL提供了成熟事务特性,高可用解决方案,又能弥补NoSQL数据库在这方面的不足。
通过Memcached协议访问表
MySQL 5.6版本开始支持通过插件Memcached Plugin,以KV方式访问表,这时可以将MySQL视作一个Memcached KV数据库。对于数据的访问不再是通过SQL接口,而是通过KV数据库中常见的get、set、incr等请求。
但为什么要通过KV的方式访问数据呢?因为有些业务对于数据库的访问本质上都是一个KV操作。比如用户登录系统,大多是用于信息确认,这时其SQL大都是通过主键或唯一索引进行数据的查询:SELECT * FROM User WHERE PK=?;
若在海量并发访问的系统中,通过SQL访问这些表,由于通过主键索引进行访问,速度很快,但SQL解析却要耗费不少时间,这时但数据库实例性能会受到一定的限制。
基于Memcached的KV访问,可以绕过SQL解析,通过映射关系,直接访问存储在InnoDB引擎中的数据,这样数据库的整体性能就会在不花费额外成本的前提下得到极大的提升。
要启用Memcached协议访问MySQL需要做两件事情:
- 开启Memcached Plugin插件;
- 配置表与KV的映射关系。
mysql>source MYSQL_HOME/share/innodb_memcached_config.sql;
mysql>INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
执行完上述操作后,会新增一个库innodb_memcache,里边的表containers就是需要配置的KV映射表。如果业务拆功能键的主键查询SQL如下,其中user_id为主键:
SELECT user_id,cellphone,last_login
FROM test.User
WEHRE user_id = ?;
那么我们可以在表Containers中插入一条记录:
INSERT INTO Containers VALUES ('User','test','user_id|cellphone|last_login','0','0','0','PRIMARY')
-- 上面的映射关系表示通过Memcached的KV方式访问,其本质时通过PRIMARY索引访问key值,key就是user_id,value值返回的是由列user_id、cellphone、last_login组合而成,分隔符为'|'的字符串
SQL VS Memcached KV
基于 Memcached 的 KV 访问方式比传统的 SQL 方式要快54.33%,而且CPU 的开销反而还要低20%。
当然了,上述操作只是将表User作为KV访问,如果想将其他表通过KV的方式访问,可以继续在表Containers中进行配置。但是在使用时,务必先通过GET命令指定要访问的表:
# Python伪代码
mc = Client('127.0.0.1:11211')
mc.get('@@User') # 读取映射表User
mc.get('key1')
mc.get('@@sbtest1') # 读取映射表sbtest1
mc.set('sb1_key1','aa|bbb|ccc')
......
另一种使用Memcached Plugin的场景时原先使用原生Memcached KV数据库的用户,这些用户可以考虑将Memcached数据库迁移到MySQL。这样的好处是:
- 通过MySQL进行访问的性能比原生Memcached好,数据库并发优化做的更好
- 存储可以持久化,支持事务,数据的一致性好
- 利用MySQL复制技术,可以弥补原生Memcached不支持数据复制的短板
通过X协议访问表
MySQL 5.7版本开始原生支持JSON二进制数据类型,同时也提供了将表格映射为一个JSON文档。同时,MySQL也提供了X Protocol这样的NoSQL访问方式,所以,现在我们可以将MySQL打造成一个SQL&NoSQL的文档数据库。
对比MongoDB文档数据库,将MySQL打造成文档数据库与MongoDB对比如下:
MySQL VS MongoDB除了MySQL目前还无法支持数据分片功能外,其他方面MySQL的优势会更大一些,特别是MySQL是通过二维表格存储JSON数据,从而实现文档数据库功能。这样可以通过SQL进行很多复杂维度的查询,特别是结合MySQL 8.0的CTE(Common Table Expression)、窗口函数(WIndow Function)等功能,而这在MongoDB中是无法原生实现的。
和Memcached Plugin不同的是,MySQL默认会自动启用X Plugin插件,接着就可以通过新的X Protocol协议访问MySQL中的数据,默认端口为33060,可以通过下面命令查看有关X Plugin的配置:
mysql> SHOW VARIABLES LIEK '%mysqlx%';
+-----------------------------------+--------------------+
| Variable_name | Value |
+-----------------------------------+--------------------+
| mysqlx_bind_address | * |
| mysqlx_compression_algorithms |
DEFLATE_STREAM,LZ4_MESSAGE,ZSTD_STREAM |
| mysqlx_connect_timeout | 30 |
| mysqlx_document_id_unique_prefix | 0 |
| mysqlx_enable_hello_notice | ON |
| mysqlx_idle_worker_thread_timeout | 60 |
| mysqlx_interactive_timeout | 28800 |
| mysqlx_max_allowed_packet | 67108864 |
| mysqlx_max_connections | 100 |
| mysqlx_min_worker_threads | 2 |
| mysqlx_port | 33060 |
...
要通过X Protocol管理MySQL需要通过新的MySQL Shell命令,默认并不安装,需要单独安装。安装后通过mysqlsh
命令通过新的X Protocol访问MySQL数据库:root@MBP-Windows:# mysqlsh root@localhost/test
X Protocol协议支持通过JS、Python、SQL的方式管理和访问MySQL
X Protocol程序员同学若要通过X Protocol来管理文档数据,也需要下载新的MySQL Connector,并引入新的X驱动库,如Python驱动:
import mysqlx
# Connect to server on localhost
session = mysqlx.get_session({
'host': 'localhost',
'port': 33060
})
schema = session.get_schema('test')
# Use the collection 'my_collection'
collection = schema.get_collection('my_collection')
# Specify which document to find with Collection.find()
result = collection.find('name like :param').bind('param', 'S%').limit(1).execute()
# Print document
docs = result.fetch_all()
print('Name: {0}'.format(docs[0]['name']))
session.close()
总结
- 通过Memcached Plugin我们可以将MySQL打造成一个KV数据库
- 通过X Protocol我们可以将MySQL打造成一个文档数据库
- MySQL底层都是通过表格的方式进行数据的存储,并且数据都存储在InnoDB引擎中
- 为什么KV数据库、文档数据库不单独使用额外的数据库呢,因为在企业的数据中心部门,会要求尽可能地收敛技术栈。这样对后续技术架构的稳定性,人员培养,长远来看会有更大的收益。
网友评论