#### 15.20.6.1 为 InnoDB memcached 插件调整现有 MySQL 模式

考虑这些方面**内存缓存**调整现有 MySQL 模式或应用程序以使用`daemon_memcached`插入：

-   **内存缓存**键不能包含空格或换行符，因为这些字符在 ASCII 协议中用作分隔符。如果您正在使用包含空格的查找值，请将它们转换或散列为不带空格的值，然后再将它们用作调用的键`添加（）`,`放（）`,`得到（）`， 等等。虽然理论上这些字符在使用二进制协议的程序的键中是允许的，但您应该限制键中使用的字符以确保与广泛的客户端兼容。

-   如果有一个短数字[首要的关键](glossary.html#glos_primary_key)列中的`InnoDB`表，将其用作唯一查找键**内存缓存**通过将整数转换为字符串值。如果**内存缓存**服务器用于多个应用程序，或与多个应用程序一起使用`InnoDB`表，考虑修改名称以确保它是唯一的。例如，在数值之前添加表名或数据库名和表名。

    笔记

    这`daemon_memcached`插件支持在映射上插入和读取`InnoDB`有一个表`整数`定义为主键。

-   您不能将分区表用于查询或存储的数据**内存缓存**.

-   这**内存缓存**协议将数值作为字符串传递。在底层证券中存储数值`InnoDB`表，实现可以在 SQL 函数中使用的计数器，例如`和（）`要么`平均（）`， 例如：

    -   采用[`VARCHAR`](char.html)具有足够字符以容纳最大预期数字的所有数字的列（如果适用于负号、小数点或两者，还包括附加字符）。

    -   在使用列值执行算术的任何查询中，使用`投掷（）`函数将值从字符串转换为整数或其他数字类型。例如：

        ```
        # 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`投掷（）`.当使用诸如`平均（）`，这取决于结果集中的行数，包括`在哪里`子句过滤掉非数字值。

-   如果`InnoDB`用作键的列的值可能超过 250 字节，将值散列到小于 250 字节。

-   将现有表与`daemon_memcached`插件，在`innodb_memcache.containers`桌子。使该表成为所有人的默认值**内存缓存**请求，指定一个值`默认`在里面`姓名`列，然后重新启动 MySQL 服务器以使更改生效。如果您将多个表用于不同类别的**内存缓存**数据，设置多个条目`innodb_memcache.containers`表与`姓名`您选择的值，然后发出**内存缓存**请求的形式`得到 @@*`姓名`*`要么`放 @@*`姓名`*`在应用程序中指定要用于后续的表**内存缓存**要求。

    对于使用预定义以外的表的示例`test.demo_test`表，见[示例 15.13，“将您自己的表与 InnoDB memcached 应用程序一起使用”](innodb-memcached-porting-mysql.html#innodb-memcached-tutorial-python).有关所需的表格布局，请参阅[第 15.20.8 节，“InnoDB memcached 插件内部”](innodb-memcached-internals.html).

-   使用多个`InnoDB`表列值与**内存缓存**键值对，指定列名，用逗号、分号、空格或管道字符分隔`值列`的领域`innodb_memcache.containers`进入`InnoDB`桌子。例如，指定`col1,col2,col3`要么`col1|col2|col3`在里面`值列`场地。

    在将字符串传递给之前，使用管道字符作为分隔符将列值连接成单个字符串**内存缓存** `添加`要么`放`来电。该字符串会自动解压缩到正确的列中。每个`得到`call 返回包含列值的单个字符串，该列值也由竖线字符分隔。您可以使用适当的应用程序语言语法解压缩这些值。

[](<>)

**示例 15.13 将您自己的表与 InnoDB memcached 应用程序一起使用**

此示例显示如何将您自己的表与一个示例 Python 应用程序一起使用，该应用程序使用`内存缓存`用于数据操作。

该示例假设`daemon_memcached`插件安装如中所述[第 15.20.3 节，“设置 InnoDB memcached 插件”](innodb-memcached-setup.html).它还假设您的系统配置为运行一个 Python 脚本，该脚本使用`蟒蛇内存缓存`模块。

1.  创建`多列`存储国家信息的表格，包括人口、地区和驾驶员侧数据（`'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=utf8mb4;
    ```

2.  插入一条记录到`innodb_memcache.containers`表，以便`daemon_memcached`插件可以访问`多列`桌子。

    ```
    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`记录为`多列`表指定一个`姓名`的价值`'bbb'`，这是表标识符。

        笔记

        如果单`InnoDB`表用于所有**内存缓存**应用程序，`姓名`值可以设置为`默认`避免使用`@@`切换表的符号。

    -   这`db_schema`列设置为`测试`，这是数据库的名称，其中`多列`表驻留。

    -   这`db_table`列设置为`多列`，这是名称`InnoDB`桌子。

    -   `键列`设置为唯一`国家`柱子。这`国家`列被定义为主键`多列`表定义。

    -   而不是单`InnoDB`表列保存复合数据值，数据在三个表列之间划分（`人口`,`area_sq_km`， 和`drive_side`）。为了容纳多个值列，在`值列`场地。中定义的列`值列`字段是存储或检索值时使用的列。

    -   的值`旗帜`,`过期时间`， 和`cas_column`字段基于在`演示.test`样品表。这些字段在使用`daemon_memcached`插件，因为 MySQL 保持数据同步，无需担心数据过期或过时。

    -   这`unique_idx_name_on_key`字段设置为`基本的`，它指的是唯一定义的主索引`国家`列中的`多列`桌子。

3.  将示例 Python 应用程序复制到文件中。在此示例中，示例脚本被复制到一个名为`multicol.py`.

    示例 Python 应用程序将数据插入到`多列`表并检索所有键的数据，演示如何访问`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 应用说明：

    -   运行应用程序不需要数据库授权，因为数据操作是通过**内存缓存**界面。唯一需要的信息是本地系统上的端口号，**内存缓存**守护进程监听。

    -   为了确保应用程序使用`多列`表`开关表（）`函数被调用，它执行一个虚拟的`得到`要么`放`请求使用`@@`符号。这`姓名`请求中的值为`bbb`， 哪一个是`多列`表中定义的标识符`innodb_memcache.containers.name`场地。

        更具描述性的`姓名`value 可能会在实际应用程序中使用。此示例仅说明指定了表标识符而不是表名`得到 @@...`要求。

    -   用于插入和查询数据的实用程序函数演示了如何将 Python 数据结构转换为管道分隔值，以便将数据发送到 MySQL`添加`要么`放`请求，以及如何解包由返回的管道分隔值`得到`要求。仅在映射单个**内存缓存**多个 MySQL 表列的值。

4.  运行示例 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
    ```

5.  查询`innodb_memcache.containers`表以查看您之前插入的记录`多列`桌子。第一条记录是样本条目`演示测试`在初始阶段创建的表`daemon_memcached`插件设置。第二条记录是您为`多列`桌子。

    ```
    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
    ```

6.  查询`多列`表以查看示例 Python 应用程序插入的数据。数据可用于 MySQL[查询](glossary.html#glos_query)，它演示了如何使用 SQL 或通过应用程序访问相同的数据（使用适当的[MySQL 连接器或 API](connectors-apis.html)）。

    ```
    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 |
    +---------+------------+------------+------------+------+------+------+
    ```

    笔记

    在定义被视为数字的列的长度时，始终允许足够的大小来容纳必要的数字、小数点、符号字符、前导零等。字符串列中的值过长，例如`VARCHAR`通过删除一些字符被截断，这可能会产生无意义的数值。

7.  （可选）在`InnoDB`存储的表**memcached**数据

    您可以通过SQL查询生成报告，跨任何列执行计算和测试，而不仅仅是数据库`国`键列。（由于以下示例仅使用少数几个国家的数据，因此这些数字仅用于说明。）以下查询返回靠右行驶的国家的平均人口，以及名称以“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 |
    +-----------------+
    ```

    因为`人口`和`面积平方公里`列存储字符数据，而不是强类型数字数据，例如`平均值（）`和`SUM（）`首先将每个值转换为一个数字。这种方法*不起作用*对于运营商，例如`<`或`>`，例如，在比较基于字符的值时，`9 > 1000`，这是不应出现在以下条款中的：`按人口顺序描述`。要获得最准确的类型处理，请对将数字列强制转换为适当类型的视图执行查询。这种技术可以让你发布简单的`挑选*`来自数据库应用程序的查询，同时确保转换、筛选和排序是正确的。下面的示例显示了一个视图，可以通过该视图按人口降序查找排名前三的国家，结果反映了世界上最新的数据`多色`表，并将人口和面积数字视为数字：

    ```
    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    |       |
    +------------+---------------------+------+-----+---------+-------+
    ```
