在调整现有 MySQL 模式或应用程序以使用
插件
时,请考虑memcached应用程序
的这些方面:daemon_memcached
memcached键不能包含空格或换行符,因为这些字符在 ASCII 协议中用作分隔符。如果您使用包含空格的查找值,请将它们转换或散列为不带空格的值,然后再将它们用作调用
add()
、set()
、get()
等的键。虽然理论上这些字符在使用二进制协议的程序的键中是允许的,但您应该限制键中使用的字符以确保与广泛的客户端兼容。如果表中有一个短数字 主键列,通过将整数转换为字符串值将其
InnoDB
用作memcached的唯一查找键。如果 memcached服务器用于多个应用程序,或者有多个InnoDB
表,请考虑修改名称以确保其唯一性。例如,在数值前加上表名或数据库名和表名。笔记该
daemon_memcached
插件支持插入和读取已定义为主键InnoDB
的映射表。INTEGER
您不能将分区表用于使用memcached查询或存储的数据。
memcached协议 将数值作为字符串传递。要在基础表中存储数值
InnoDB
,以实现可在 SQL 函数(例如SUM()
or )中使用的计数器,AVG()
例如:使用
VARCHAR
具有足够字符的列来容纳最大预期数字的所有数字(如果适用于负号、小数点或两者,还可以使用其他字符)。在任何使用列值执行算术的查询中,使用该
CAST()
函数将值从字符串转换为整数,或转换为其他一些数字类型。例如:# Alphabetic entries are returned as zero. SELECT CAST(c2 as unsigned integer) FROM demo_test; # Since there could be numeric values of 0, can't disqualify them. # Test the string values to find the ones that are integers, and average only those. SELECT AVG(cast(c2 as unsigned integer)) FROM demo_test WHERE c2 BETWEEN '0' and '9999999999'; # Views let you hide the complexity of queries. The results are already converted; # no need to repeat conversion functions and WHERE clauses each time. CREATE VIEW numbers AS SELECT c1 KEY, CAST(c2 AS UNSIGNED INTEGER) val FROM demo_test WHERE c2 BETWEEN '0' and '9999999999'; SELECT SUM(val) FROM numbers;
笔记通过调用 将结果集中的任何字母值转换为 0
CAST()
。AVG()
使用取决于结果集中行数的函数(例如 )时,请包含WHERE
子句以过滤掉非数字值。
如果
InnoDB
用作键的列的值可能超过 250 个字节,则将值散列为小于 250 个字节。要将现有表与
daemon_memcached
插件一起使用,请在表中为其定义一个条目innodb_memcache.containers
。要使该表成为所有 memcacheddefault
请求的默认表,请在列中指定一个值name
,然后重新启动 MySQL 服务器以使更改生效。如果您为不同类别的memcachedinnodb_memcache.containers
数据使用多个表,请在表中使用您选择的 值设置多个条目 ,然后以或 的形式name
发出 memcached请求get @@
name
set @@
在应用程序中指定要用于后续memcached请求的表。name
有关使用预定义表以外的表的 示例
test.demo_test
,请参阅 示例 14.13,“将您自己的表与 InnoDB memcached 应用程序一起使用”。对于所需的表布局,请参阅 第 14.21.7 节,“InnoDB memcached 插件内部”。要将多个
InnoDB
表列值与memcached键值对一起使用,请在表 条目的value_columns
字段中指定以逗号、分号、空格或竖线字符分隔的列名。例如,在 字段 中指定或 。innodb_memcache.containers
InnoDB
col1,col2,col3
col1|col2|col3
value_columns
在将字符串传递给memcached
add
或set
调用 之前,使用竖线字符作为分隔符将列值连接成单个字符串 。该字符串会自动解压缩到正确的列中。每次get
调用都会返回一个包含列值的字符串,该列值也由竖线字符分隔。您可以使用适当的应用程序语言语法解压这些值。
示例 14.13 在 InnoDB memcached 应用程序中使用您自己的表
此示例说明如何将您自己的表与memcached
用于数据操作的示例 Python 应用程序一起使用。
该示例假定
daemon_memcached
已按照第 14.21.3 节“设置 InnoDB memcached 插件”中的说明安装插件。它还假设您的系统配置为运行使用该python-memcache
模块的 Python 脚本。
创建
multicol
存储国家信息的表,包括人口、面积和驾驶员侧数据('R'
右侧和'L'
左侧)。mysql> USE test; mysql> CREATE TABLE `multicol` ( `country` varchar(128) NOT NULL DEFAULT '', `population` varchar(10) DEFAULT NULL, `area_sq_km` varchar(9) DEFAULT NULL, `drive_side` varchar(1) DEFAULT NULL, `c3` int(11) DEFAULT NULL, `c4` bigint(20) unsigned DEFAULT NULL, `c5` int(11) DEFAULT NULL, PRIMARY KEY (`country`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
向表中插入一条记录,
innodb_memcache.containers
以便daemon_memcached
插件可以访问该multicol
表。mysql> INSERT INTO innodb_memcache.containers (name,db_schema,db_table,key_columns,value_columns,flags,cas_column, expire_time_column,unique_idx_name_on_key) VALUES ('bbb','test','multicol','country','population,area_sq_km,drive_side', 'c3','c4','c5','PRIMARY'); mysql> COMMIT;
表的
innodb_memcache.containers
记录multicol
指定name
值'bbb'
,这是表标识符。笔记如果单个
InnoDB
表用于所有memcached应用程序,该name
值可以设置default
为避免使用@@
符号切换表。该
db_schema
列设置为test
,这是multicol
表所在的数据库的名称。该
db_table
列设置为multicol
,这是InnoDB
表的名称。key_columns
设置为唯一country
列。该 列在表定义country
中被定义为主键。multicol
数据不是由单个
InnoDB
表列来保存复合数据值,而是分为三个表列(population
、area_sq_km
和drive_side
)。value_columns
为了容纳多个值列,在该字段中指定了一个以逗号分隔的列列表 。字段中定义的value_columns
列是存储或检索值时使用的列。flags
、expire_time
和 字段的 值cas_column
基于demo.test
示例表中使用的值。这些字段在使用该插件的应用程序中通常并不重要,daemon_memcached
因为 MySQL 保持数据同步,并且无需担心数据过期或变得陈旧。该
unique_idx_name_on_key
字段设置为PRIMARY
,它指的country
是表中唯一列 上定义的主索引multicol
。
将示例 Python 应用程序复制到一个文件中。在此示例中,示例脚本被复制到一个名为
multicol.py
.示例 Python 应用程序将数据插入
multicol
表中并检索所有键的数据,演示如何 通过插件 访问InnoDB
表 。daemon_memcached
import sys, os import memcache def connect_to_memcached(): memc = memcache.Client(['127.0.0.1:11211'], debug=0); print "Connected to memcached." return memc def banner(message): print print "=" * len(message) print message print "=" * len(message) country_data = [ ("Canada","34820000","9984670","R"), ("USA","314242000","9826675","R"), ("Ireland","6399152","84421","L"), ("UK","62262000","243610","L"), ("Mexico","113910608","1972550","R"), ("Denmark","5543453","43094","R"), ("Norway","5002942","385252","R"), ("UAE","8264070","83600","R"), ("India","1210193422","3287263","L"), ("China","1347350000","9640821","R"), ] def switch_table(memc,table): key = "@@" + table print "Switching default table to '" + table + "' by issuing GET for '" + key + "'." result = memc.get(key) def insert_country_data(memc): banner("Inserting initial data via memcached interface") for item in country_data: country = item[0] population = item[1] area = item[2] drive_side = item[3] key = country value = "|".join([population,area,drive_side]) print "Key = " + key print "Value = " + value if memc.add(key,value): print "Added new key, value pair." else: print "Updating value for existing key." memc.set(key,value) def query_country_data(memc): banner("Retrieving data for all keys (country names)") for item in country_data: key = item[0] result = memc.get(key) print "Here is the result retrieved from the database for key " + key + ":" print result (m_population, m_area, m_drive_side) = result.split("|") print "Unpacked population value: " + m_population print "Unpacked area value : " + m_area print "Unpacked drive side value: " + m_drive_side if __name__ == '__main__': memc = connect_to_memcached() switch_table(memc,"bbb") insert_country_data(memc) query_country_data(memc) sys.exit(0)
示例 Python 应用说明:
运行应用程序不需要数据库授权,因为数据操作是通过memcached接口执行的。唯一需要的信息是 memcached守护程序侦听的本地系统上的端口号。
为确保应用程序使用该
multicol
表,将调用该 函数,该函数使用符号switch_table()
执行虚拟get
或set
请求 。@@
请求中的name
值为bbb
,即 字段multicol
中定义的表标识innodb_memcache.containers.name
。name
在实际应用程序中可能会使用 更具描述性的值。get @@...
此示例仅说明在请求 中指定了表标识符而不是表名。用于插入和查询数据的实用函数演示了如何将 Python 数据结构转换为管道分隔值,以便使用
add
或set
请求将数据发送到 MySQL,以及如何解压缩get
请求返回的管道分隔值。只有在将单个memcached值映射到多个 MySQL 表列 时才需要进行此额外处理。
运行示例 Python 应用程序。
$> python multicol.py
如果成功,示例应用程序将返回以下输出:
Connected to memcached. Switching default table to 'bbb' by issuing GET for '@@bbb'. ============================================== Inserting initial data via memcached interface ============================================== Key = Canada Value = 34820000|9984670|R Added new key, value pair. Key = USA Value = 314242000|9826675|R Added new key, value pair. Key = Ireland Value = 6399152|84421|L Added new key, value pair. Key = UK Value = 62262000|243610|L Added new key, value pair. Key = Mexico Value = 113910608|1972550|R Added new key, value pair. Key = Denmark Value = 5543453|43094|R Added new key, value pair. Key = Norway Value = 5002942|385252|R Added new key, value pair. Key = UAE Value = 8264070|83600|R Added new key, value pair. Key = India Value = 1210193422|3287263|L Added new key, value pair. Key = China Value = 1347350000|9640821|R Added new key, value pair. ============================================ Retrieving data for all keys (country names) ============================================ Here is the result retrieved from the database for key Canada: 34820000|9984670|R Unpacked population value: 34820000 Unpacked area value : 9984670 Unpacked drive side value: R Here is the result retrieved from the database for key USA: 314242000|9826675|R Unpacked population value: 314242000 Unpacked area value : 9826675 Unpacked drive side value: R Here is the result retrieved from the database for key Ireland: 6399152|84421|L Unpacked population value: 6399152 Unpacked area value : 84421 Unpacked drive side value: L Here is the result retrieved from the database for key UK: 62262000|243610|L Unpacked population value: 62262000 Unpacked area value : 243610 Unpacked drive side value: L Here is the result retrieved from the database for key Mexico: 113910608|1972550|R Unpacked population value: 113910608 Unpacked area value : 1972550 Unpacked drive side value: R Here is the result retrieved from the database for key Denmark: 5543453|43094|R Unpacked population value: 5543453 Unpacked area value : 43094 Unpacked drive side value: R Here is the result retrieved from the database for key Norway: 5002942|385252|R Unpacked population value: 5002942 Unpacked area value : 385252 Unpacked drive side value: R Here is the result retrieved from the database for key UAE: 8264070|83600|R Unpacked population value: 8264070 Unpacked area value : 83600 Unpacked drive side value: R Here is the result retrieved from the database for key India: 1210193422|3287263|L Unpacked population value: 1210193422 Unpacked area value : 3287263 Unpacked drive side value: L Here is the result retrieved from the database for key China: 1347350000|9640821|R Unpacked population value: 1347350000 Unpacked area value : 9640821 Unpacked drive side value: R
查询该
innodb_memcache.containers
表以查看您之前为该multicol
表插入的记录。第一条记录是demo_test
在初始daemon_memcached
插件设置期间创建的表的样本条目。第二条记录是您为表插入的条目multicol
。mysql> SELECT * FROM innodb_memcache.containers\G *************************** 1. row *************************** name: aaa db_schema: test db_table: demo_test key_columns: c1 value_columns: c2 flags: c3 cas_column: c4 expire_time_column: c5 unique_idx_name_on_key: PRIMARY *************************** 2. row *************************** name: bbb db_schema: test db_table: multicol key_columns: country value_columns: population,area_sq_km,drive_side flags: c3 cas_column: c4 expire_time_column: c5 unique_idx_name_on_key: PRIMARY
查询
multicol
表以查看示例 Python 应用程序插入的数据。数据可用于 MySQL 查询,它演示了如何使用 SQL 或通过应用程序(使用适当的 MySQL 连接器或 API)访问相同的数据。mysql> SELECT * FROM test.multicol; +---------+------------+------------+------------+------+------+------+ | country | population | area_sq_km | drive_side | c3 | c4 | c5 | +---------+------------+------------+------------+------+------+------+ | Canada | 34820000 | 9984670 | R | 0 | 11 | 0 | | China | 1347350000 | 9640821 | R | 0 | 20 | 0 | | Denmark | 5543453 | 43094 | R | 0 | 16 | 0 | | India | 1210193422 | 3287263 | L | 0 | 19 | 0 | | Ireland | 6399152 | 84421 | L | 0 | 13 | 0 | | Mexico | 113910608 | 1972550 | R | 0 | 15 | 0 | | Norway | 5002942 | 385252 | R | 0 | 17 | 0 | | UAE | 8264070 | 83600 | R | 0 | 18 | 0 | | UK | 62262000 | 243610 | L | 0 | 14 | 0 | | USA | 314242000 | 9826675 | R | 0 | 12 | 0 | +---------+------------+------------+------------+------+------+------+
笔记在定义被视为数字的列的长度时,始终允许足够的大小来容纳必要的数字、小数点、符号字符、前导零等。字符串列中的太长值(例如 a
VARCHAR
)会通过删除一些字符来截断,这可能会产生无意义的数值。或者,对存储memcached数据 的
InnoDB
表 运行报告类型的查询 。您可以通过 SQL 查询生成报告,跨任何列执行计算和测试,而不仅仅是
country
键列。(因为以下示例仅使用少数几个国家/地区的数据,所以数字仅供说明之用。)以下查询返回人们靠右行驶的国家/地区的平均人口,以及名称以“ U ”开头的国家/地区的平均面积”:mysql> SELECT AVG(population) FROM multicol WHERE drive_side = 'R'; +-------------------+ | avg(population) | +-------------------+ | 261304724.7142857 | +-------------------+ mysql> SELECT SUM(area_sq_km) FROM multicol WHERE country LIKE 'U%'; +-----------------+ | sum(area_sq_km) | +-----------------+ | 10153885 | +-----------------+
因为
population
andarea_sq_km
列存储字符数据而不是强类型数字数据,所以函数(例如AVG()
andSUM()
)首先将每个值转换为数字。这种方法 不适用于<
or之类的运算符>
,例如,在比较基于字符的值时9 > 1000
,这是子句中所不期望的,例如ORDER BY population DESC
. 要获得最准确的类型处理,请针对将数字列转换为适当类型的视图执行查询。这种技术可以让你发出简单的SELECT *
来自数据库应用程序的查询,同时确保转换、过滤和排序是正确的。以下示例显示了一个视图,可以查询该视图以按人口降序查找前三个国家,结果反映multicol
表中的最新数据,并将人口和面积数字视为数字:mysql> CREATE VIEW populous_countries AS SELECT country, cast(population as unsigned integer) population, cast(area_sq_km as unsigned integer) area_sq_km, drive_side FROM multicol ORDER BY CAST(population as unsigned integer) DESC LIMIT 3; mysql> SELECT * FROM populous_countries; +---------+------------+------------+------------+ | country | population | area_sq_km | drive_side | +---------+------------+------------+------------+ | China | 1347350000 | 9640821 | R | | India | 1210193422 | 3287263 | L | | USA | 314242000 | 9826675 | R | +---------+------------+------------+------------+ mysql> DESC populous_countries; +------------+---------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+---------------------+------+-----+---------+-------+ | country | varchar(128) | NO | | | | | population | bigint(10) unsigned | YES | | NULL | | | area_sq_km | int(9) unsigned | YES | | NULL | | | drive_side | varchar(1) | YES | | NULL | | +------------+---------------------+------+-----+---------+-------+