这是《高性能 MySQL(第三版)》第四章《Schema 与数据类型优化》的读书笔记。

1. 选择优化的数据类型

数据类型的选择原则:

  • 越小越好:选择满足需求的最小类型。注意,增大数据类型的范围是耗时操作,尽量避免。
  • 简单:整型比字符操作代价更低。
  • 尽量避免 NULL 列:列最好指定为 NOT NULL,除非确实可以是 NULL。如果查询中包含可为 NULL 的列,会使索引、索引统计和值比较都更复杂。可为 NULL 的列占用更多存储空间,在 MySQL 里也需要特殊处理。如果可为 NULL 的列被索引,每个索引记录需要一个额外的字节,在 MyISAM 里甚至可能导致固定大小的索引变成可变大小的索引。

    把 NULL 列改为 NOT NULL 列带来的性能提升比较小,但是用于索引的列最好是 NOT NULL。另外,InnoDB 使用单独的位(bit)存储 NULL 值,包含很多 NULL 值的稀疏数据的空间效率比较高。

首先选择大类型:数字、字符串、时间、布尔值等。然后选择具体类型。

1.1 整数类型

可用的整型数据有:

  • TINYINT:8 bit。
  • SMALLINT:16 bit。
  • MEDIUMINT:24 bit。
  • INT:32 bit。
  • BIGINT:64 bit。

所有的整数类型都支持 UNSIGNED 属性,表示无符号数据,例如 TINYINT UNSIGNED。有符号和无符号整型数据存储空间一样,性能一样。

MySQL 中可以为整数类型指定宽度,例如 INT(11),这个宽度只是规定了 MySQL 交互工具用来显示字符的个数,不影响存储和计算。

1.2 实数类型

可用的实数数据有:

  • 浮点类型:

    • FLOAT:32 bit。不精确类型,支持浮点运算。
    • DOUBLE:64 bit。不精确类型,支持浮点运算。
  • DECIMAL:最多允许 65 个数字,例如 DECIMAL(33,32)DECIMAL(65,0)。可以存储精确的小数,也可以存储比 BIGINT 还大的整数,支持精确计算。因为 CPU 不支持对 DECIMAL 的直接计算,所以 MySQL 服务器自身实现了 DECIMAL 的高精度计算。

MySQL 支持精确类型(DECIMAL),也支持不精确类型(浮点类型,即 FLOAT 和 DOUBLE)。

FLOAT、DOUBLE 和 DECIMAL 类型都可以指定精度。例如 DOUBLE(12,3) 表示最多 9 位整数、3 位小数。DECIMAL(18,9) 表示小数点两边各存储 9 个数字,一共使用 9 个字节(小数点占一个字节)。

DECIMAL 需要的存储空间大,计算开销高,如果数据量很大,可以考虑用 BIGINT 替代 DECIMAL。例如金额需要保证 0.001 的精度,则可以将所有金额乘以 1000 后取整存入 BIGINT 类型的字段,从而避免浮点数计算不准确和 DECIMAL 精确计算代价高的问题。

1.3 字符串类型

MySQL 中每个字符串列可以定义自己的字符集和排列规则(校对规则,collation)。

1.3.1 VARCHAR 和 CHAR 类型

MySQL 中最重要的字符串类型,其在内存和磁盘中的存储方式跟存储引擎相关。这里假设用的是 InnoDB 或 MyISAM 引擎。

  • VARCHAR:变长字符串,节省空间(但是如果用 ROW_FORMAT = FIXED 创建表,每行都会定长存储,浪费空间)。需要 1 个或 2 个额外字节记录字符串长度(如果列的最大长度小于等于 255 字节则只需要 1 个字节,否则需要 2 个字节)。例如,对于 latin1 字符集,一个 VARCHAR(10) 的列需要 11 个字节的存储空间,VARCHAR(1000) 的列需要 1002 个字节的存储空间。

    在执行 UPDATA 操作时,如果需要增大行的长度,需要额外工作。如果磁盘当前页的空间不够,不同存储引擎的处理方式不同。MyISAM 会将行拆成不同的片段存储,InnoDB 则需要分裂页来使行可以放进页内。InnoDB 会把过长的 VARCHAR 存储为 BLOB。
  • CHAR:定长字符串,分配固定空间,如果字符串长度小于存储空间,则剩余空间填充空格。对于单字节字符集,CHAR(1) 只需要一个字节,而 VARCHAR(1) 则需要两个字节(包括记录长度的一个字节)。
  • VARBINARY:二进制变长字符串,存储字节码而不是字符。
  • BINARY:二进制定长字符串,存储字节码而不是字符,使用 \0(零字节)填充而不是空格,且检索时不会去掉填充值。

适合使用 VARCHAR 的场景:

  • 字符串列的最大长度比平均长度大得多
  • 列很少更新,所以碎片不是问题
  • 使用 UTF-8 字符集,每个字符用不同的字节数进行存储

适合使用 CHAR 的场景:

  • 短字符串
  • 定长字符串,例如密码的 HASH 值
  • 经常变更的字符串,不易产生碎片

注意:CHAR 类型的字符串在存储时,会自动截断字符串末尾的空格:

MariaDB [foo]> CREATE TABLE char_test(char_col CHAR(10));
Query OK, 0 rows affected (0.04 sec) MariaDB [foo]> INSERT INTO char_test(char_col) VALUES
-> ('string1'), (' string2'), ('string3 ');
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0 MariaDB [foo]> SELECT CONCAT("'", char_col, "'") FROM char_test;
+----------------------------+
| CONCAT("'", char_col, "'") |
+----------------------------+
| 'string1' |
| ' string2' |
| 'string3' |
+----------------------------+
3 rows in set (0.00 sec)

VARCHAR 类型的字符串在存储时,则不会截断字符串末尾的空格:

MariaDB [foo]> CREATE TABLE varchar_test(varchar_col VARCHAR(10));
Query OK, 0 rows affected (0.04 sec) MariaDB [foo]> INSERT INTO varchar_test VALUES
-> ('string1'), (' string2'), ('string3 ');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0 MariaDB [foo]> SELECT CONCAT("'", char_col, "'") FROM varchar_test;
+----------------------------+
| CONCAT("'", char_col, "'") |
+----------------------------+
| 'string1' |
| ' string2' |
| 'string3 ' |
+----------------------------+
3 rows in set (0.00 sec)

1.3.2 BLOB 和 TEXT 类型

BLOB:二进制方式存储大数据的字符串类型,没有字符集和排序规则。具体的类型有:TINYBLOB, SMALLBLOB, BLOB, MIDIUMBLOB, LONGBLOB

TEXT:字符方式存储大数据的字符串类型,有字符集和排序规则。具体的类型有:TINYTEXT, SMALLTEXT, TEXT, MIDIUMTEXT, LONGTEXT

在 MySQL 中,每个 BLOB 和 TEXT 类型的值都是独立对象。当值太大时,InnoDB 还会使用专门的外部存储区域来存储,此时行内只需 1-4 个字节存储指针。

1.3.3 ENUM 枚举类型代替字符串

使用枚举类型可以节省存储空间。MySQL 内部将每个枚举类型的字段存储为整数,并在表的 .frm 文件中保存“数字-字符串”映射关系的“查找表”。

MariaDB [foo]> CREATE TABLE enum_test( e ENUM('dog', 'fish', 'apple') NOT NULL);
Query OK, 0 rows affected (0.17 sec) MariaDB [foo]> desc enum_test;
+-------+----------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------------------------+------+-----+---------+-------+
| e | enum('dog','fish','apple') | NO | | NULL | |
+-------+----------------------------+------+-----+---------+-------+
1 row in set (0.01 sec) MariaDB [foo]> INSERT INTO enum_test(e) VALUES('fish'), ('dog'), ('apple');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0

MySQL 的枚举字段存储的实际上是数字而不是字符串:

MariaDB [foo]> SELECT e + 0 FROM enum_test;      <-------实际存储整数值
+-------+
| e + 0 |
+-------+
| 2 |
| 1 |
| 3 |
+-------+
3 rows in set (0.00 sec) MariaDB [foo]> SELECT e FROM enum_test; <-------取数据时自动转为字符串
+-------+
| e |
+-------+
| fish |
| dog |
| apple |
+-------+
3 rows in set (0.00 sec)

枚举字段排序时,默认按照内部存储的整数进行排序。可以使用 FIELD() 函数显式指定排序顺序,但会导致 MySQL 无法利用索引消除排序:

MariaDB [foo]> SELECT e FROM enum_test ORDER BY e;      <-------排序时,根据实际存储的整数值排序
+-------+
| e |
+-------+
| dog |
| fish |
| apple |
+-------+
6 rows in set (0.06 sec) MariaDB [foo]> SELECT e FROM enum_test ORDER BY FIELD(e, 'apple', 'dog', 'fish'); <-------自己制定排序方式
+-------+
| e |
+-------+
| apple |
| dog |
| fish |
+-------+
6 rows in set (0.00 sec)

枚举字段如果需要增删可用的枚举值,则需要使用 ALTER TABLE。如果枚举类型添加字符串,MySQL 会自动修改字段中保存的整数值以匹配字符串。为了不重建整个表,最好在列表末尾新增加字符串:

MariaDB [foo]> ALTER TABLE enum_test MODIFY e ENUM('dog', 'fish', 'apple', 'banana');
Query OK, 6 rows affected (0.08 sec)
Records: 6 Duplicates: 0 Warnings: 0 MariaDB [foo]> DESC enum_test;
+-------+-------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------------------------------+------+-----+---------+-------+
| e | enum('dog','fish','apple','banana') | YES | | NULL | |
+-------+-------------------------------------+------+-----+---------+-------+
1 row in set (0.00 sec) MariaDB [foo]> SELECT e + 0 FROM enum_test; <-------存储的整数值不受影响
+-------+
| e + 0 |
+-------+
| 2 |
| 1 |
| 3 |
+-------+
3 rows in set (0.00 sec) MariaDB [foo]> ALTER TABLE enum_test MODIFY e ENUM('test', 'dog', 'fish', 'apple', 'banana');
Query OK, 6 rows affected (0.04 sec)
Records: 6 Duplicates: 0 Warnings: 0 MariaDB [foo]> SELECT e + 0 FROM enum_test; <-------存储的整数值受影响
+-------+
| e + 0 |
+-------+
| 3 |
| 2 |
| 4 |
+-------+
6 rows in set (0.00 sec) MariaDB [foo]> SELECT e FROM enum_test; <-------实际读出来的字符串不会变化
+-------+
| e |
+-------+
| fish |
| dog |
| apple |
+-------+
6 rows in set (0.00 sec)

1.4 日期和时间类型

  • DATETIME:时间范围 1001 - 9999 年,精度范围 1 秒。内部把日期和时间封装到格式为 YYYYMMDDHHMMSS 的整数中,与时区无关,使用 8 个字节的存储空间。MySQL 默认以可排序、无歧义的格式显示 DATETIME 的值,例如 “2018-04-26 16:51:05”。
  • TIMESTAMP:时间范围 1970 - 2038 年,保存从 1970 年 1 月 1 日凌时开始的秒数,跟 UNIX 的时间戳一样。只使用 4 个字节的存储空间。

    TIMESTAMP 显示的值依赖于时区,操作系统、MySQL 服务器及客户端都有时区设置。例如,存储值为 0 的 TIMESTAMP 在中国(东八区)显示为“1970-01-01 08:00:00”。如果跨时区访问或存储数据,TIMESTAMP 和 DATETIME 的行为完全不一样。
  • DATE:占用 4 个字节。表示 年月日 YYYY-MM-DD,范围 1000 - 9999。
  • TIME:占用 3 个字节。表示 时分秒 HH:MM:SS。
  • YEAR:占用 1 个字节。表示 年 YYYY,范围 1901 - 2155。

TIMESTAMP 的规则相当复杂,且在不同版本的 MySQL 中会发生变化。如果需要跨时区的人使用,最好使用 TIMESTAMP。常见的特殊属性有:

  • 创建表时,所有的 TIMESTAMP 字段默认为 NOT NULL,且第一个 TIMESTAMP 字段有默认值 CURRENT_TIMESTAMP。
  • INSERT 插入数据时,如果没有指定第一个 TIMESTAMP 列的值,MySQL 会设置这个列的值为当前时间。
  • UPDATE 更新数据时,MySQL 会默认更新第一个 TIMESTAMP 列的值为当前时间(除非明确指定值)。

MySQL 内置函数可以实现时间戳和日期的互相转换:

  • FROM_UNIXTIME():将 UNIX 时间戳转为日期。
  • UNIX_TIMESTAMP():将日期转为 UNIX 时间戳。
MariaDB [foo]> CREATE TABLE t_test (id INT, t1 TIMESTAMP, t2 TIMESTAMP, d1 DATETIME, d2 DATETIME);
Query OK, 0 rows affected (0.13 sec) MariaDB [foo]> DESC t_test;
+-------+-----------+------+-----+---------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+---------------------+-----------------------------+
| id | int(11) | YES | | NULL | |
| t1 | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | <------第一个 TIMESTAMP 字段会默认填充当前时间,且在更新数据时同步刷新
| t2 | timestamp | NO | | 0000-00-00 00:00:00 | | <------第二个 TIMESTAMP 字段会默认填充 0000-00-00 00:00:00
| d1 | datetime | YES | | NULL | |
| d2 | datetime | YES | | NULL | |
+-------+-----------+------+-----+---------------------+-----------------------------+
5 rows in set (0.01 sec) MariaDB [foo]> CREATE TABLE time_test (id INT, stamp TIMESTAMP, time DATETIME);
Query OK, 0 rows affected (0.18 sec) MariaDB [foo]> desc time_test;
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+-----------------------------+
| id | int(11) | YES | | NULL | |
| stamp | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| time | datetime | YES | | NULL | |
+-------+-----------+------+-----+-------------------+-----------------------------+
3 rows in set (0.02 sec) MariaDB [foo]> INSERT INTO time_test VALUES(1, null, '2018-04-27 09:27:00');
Query OK, 1 row affected (0.00 sec) MariaDB [foo]> SELECT * FROM time_test;
+------+---------------------+---------------------+
| id | stamp | time |
+------+---------------------+---------------------+
| 1 | 2018-04-27 09:28:25 | 2018-04-27 09:27:00 | <------插入时,TIMESTAMP 会默认填充当前时间
+------+---------------------+---------------------+
1 row in set (0.00 sec) MariaDB [foo]> SELECT stamp + 0 FROM time_test;
+----------------+
| stamp + 0 |
+----------------+
| 20180427092825 |
+----------------+
1 row in set (0.00 sec) MariaDB [foo]> SELECT time + 0 FROM time_test;
+----------------+
| time + 0 |
+----------------+
| 20180427092700 |
+----------------+
1 row in set (0.00 sec) MariaDB [foo]> UPDATE time_test SET id = 2 WHERE id = 1;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0 MariaDB [foo]> SELECT * FROM time_test;
+------+---------------------+---------------------+
| id | stamp | time |
+------+---------------------+---------------------+
| 2 | 2018-04-27 09:30:02 | 2018-04-27 09:27:00 | <------更新时,TIMESTAMP 会默认更新为当前时间
+------+---------------------+---------------------+
1 row in set (0.00 sec)

1.5 位数据类型

MySQL 中的位类型从技术上看都是字符串类型。

1.5.1 BIT(不建议用)

BIT 列中可以存储一个或多个 true/false 值。BIT(n) 定义了存储 n 个位的字段,BIT 列最大支持 64 个位。

BIT 的行为因存储引擎的不同而不同。MyISAM 会打包存储所有的 BIT 列,17 个单独的 BIT 列只需要 17 个位存储(假设没有可为 NULL 的列),只需要 3 个字节。假设存储引擎是 Memory 或 InnoDB,每个 BIT 列使用一个足够存储的最小整数来存放,无法节省存储空间。

MySQL 把 BIT 当做字符串类型,而不是数字类型。当检索 BIT(1) 的值时,结果是一个包含二进制 0 或 1 的字符串,而不是 ASCII 码的 0 或 1。但是在数字上下文的场景中,会自动将位字符转为对应的 ASCII 码。例如,对于存储了 b'00111001' 的 BIT(8) 列,正常检索时得到字符码为 57 的字符‘9’,但是在数字上下文场景中,得到数字 57:

MariaDB [foo]> CREATE TABLE bit_test(a BIT(8));
Query OK, 0 rows affected (0.01 sec) MariaDB [foo]> INSERT INTO bit_test VALUES(b'00111001');
Query OK, 1 row affected (0.02 sec) MariaDB [foo]> SELECT a, a + 0 FROM bit_test;
+------+-------+
| a | a + 0 |
+------+-------+
| 9 | 57 |
+------+-------+
1 row in set (0.00 sec)

1.5.2 SET

如果需要保存很多 true/false 值,可以合并这些列到一个 SET 数据类型,在 MySQL 内部以一系列打包的位的集合来表示。存储空间利用率高,使用方便(可以在查询中使用 FIELD()FIELD() 函数)。缺点是改变列的定义时,代价较高(需要使用 ALTER TABLE),对于大表很麻烦。

1.6 选择标识符

标识列(identifier column)选择合适的数据类型很重要。标识列可以与其他值进行比较,或通过标识列寻找其他列。标识列也可以作为其他表中的外键。

选择标识列的类型时,既要考虑存储类型,也要考虑 MySQL 对这种类型怎么执行计算和比较。例如 MySQL 内部用整数存储 ENUM 和 SET 类型,在比较操作时转为字符串。

整数类型

整数是标识列最佳选择,快,且可以使用 AUTO_INCREMENT。

ENUM 和 SET 类型

标识列的糟糕选择。ENUM 和 SET 列适合存储固定信息,例如性别、产品类型。

字符串类型

尽量避免,慢,存储空间大。尤其是 MyISAM,会对字符串压缩索引。

1.7 特殊类型数据

例如低于秒级精度的时间戳。对于 IPv4 地址,可以使用无符号整数存储,MySQL 提供了 INET_ATON() 和 INET_NTOA() 函数进行转换。

2. MySQL schema 设计中的陷阱

太多列

MySQL 的存储引擎 API 工作时需要在服务器层和存储引擎层之间通过行缓冲格式拷贝数据,然后在服务器层将缓冲内容解码成各个列。MyISAM 的变长行和 InnoDB 的行结构都需要转换。

太多关联

单个查询最多在 12 个表内做关联。

全能的枚举

变相的枚举

NULL

3. 范式和反范式

范式化数据库中,每个事实数据会出现且只出现一次。反范式化数据库中,信息是冗余的,可能存储在多处。

范式化的优点:

  • 更新操作快
  • 较好的范式化可以减少数据冗余,修改简单
  • 范式化好的表更新
  • 冗余少的数据可以更少的使用 DISTINCT 或 GROUP BY 语句

范式化设计的 schema 的缺点是通常需要关联查询

反范式化的优点:所有数据都在一张表中,避免了关联。

最常见的混用范式化和反范式化的例子是复制或缓存,在不同的表中存储相同的特定列。可以通过触发器更新冗余列。

4. 缓存表和汇总表

完全独立的缓存表和汇总表,可以存储少量冗余数据。

缓存表是实时维护的。

汇总表是定期重建的。

可以使用物化视图(MySQL 需要借助工具 Flexviews)和计数器表。

5. 加快 ALTER TABLE 操作的速度

MySQL 执行 ALTER TABLE 时,通常是用新的结构创建一个空表,从旧表中查出所有数据插入新表,再删除旧表。

大部分 ALTER TABLE 操作会中断 MySQL 服务。有几种方式可以避免停机:

  • 主备结构时,可以在不提供服务的备用库执行操作,完成后再主备切换。
  • 影子拷贝:用新的表结构创建新表,然后通过重命名和删表操作交换两张表。可以使用 Facebook 的“online schema change”工具。

改变或删除列的默认值时,可以使用 ALTER COLUMN(不一定重建表)或 MODIFY COLUMN(需要重建表)。列的默认值存储在表的 .frm 文件中,

5.1 只修改 .frm 文件

有风险。。。

5.2 快速创建 MyISAM 索引

ALTER TABLE 时,先禁用索引,载入数据后再启用索引,可以高效载入数据。

Schema 与数据类型优化的更多相关文章

  1. mysql笔记01 MySQL架构与历史、Schema与数据类型优化

    MySQL架构与历史 1. MySQL架构推荐参考:http://www.cnblogs.com/baochuan/archive/2012/03/15/2397536.html 2. MySQL会解 ...

  2. MySQL Schema与数据类型优化

    Schema与数据类型优化 选择优化的数据类型 1.更小的通常更好 更小的数据类型通常更快,因为它们占用更少的磁盘,内存和CPU缓存 2.简单就好 简单数据类型的操作通常需要更少的CPU周期.例如:整 ...

  3. MySQL设计之Schema与数据类型优化

    一.数据类型优化 1.更小通常更好 应该尽量使用可以正确存储数据的最小数据类型,更小的数据类型通常更快,因为它们占用更少的磁盘.内存和CPU缓存,并且处理时需要的CPU周期更少,但是要确保没有低估需要 ...

  4. 高性能MySQL笔记 第4章 Schema与数据类型优化

    4.1 选择优化的数据类型   通用原则   更小的通常更好   前提是要确保没有低估需要存储的值范围:因为它占用更少的磁盘.内存.CPU缓存,并且处理时需要的CPU周期也更少.   简单就好   简 ...

  5. Schema与数据类型优化

    良好的逻辑设计和物理设计是高性能的基石,应该根据系统将要执行的查询数据来设计schema,这往往需要权衡各种因素. MySQL支持的数据类型非常多,选择正确的数据类型对于获得高性能至关重要. 更小的通 ...

  6. Mysql高性能笔记(一):Schema与数据类型优化

    1.数据类型 1.1.几个参考优化原则 a.  更小的通常更好 i.更小的数据类型,占用更少磁盘.内存和CPU缓存,需要的CPU周期更少 ii.如果无法确定哪个数据类型是最好的,就选择不会超过范围的最 ...

  7. MySQL之Schema与数据类型优化

    选择优化的数据类型 MySQL支持的数据类型非常多,选择正确的数据类型对于获得高性能至关重要.不管存储哪种类型的数据,下面几个简单的原则都有助于做出更好的选择: 更小的通常更好一般情况下,应该尽量使用 ...

  8. (三)Schema与数据类型优化

    1.Schema schema,中文叫模式,是数据库的组织和结构 2.选择优化的数据类型 更小的通常更好:尽量使用可以正确存储数据的最小数据类型 简单就好:简单数据类型的操作通常需要更少的cpu周期. ...

  9. 深入学习MySQL 03 Schema与数据类型优化

    Schema是什么鬼 schema就是数据库对象的集合,这个集合包含了各种对象如:表.视图.存储过程.索引等.为了区分不同的集合,就需要给不同的集合起不同的名字,默认情况下一个用户对应一个集合,用户的 ...

随机推荐

  1. C# TCPListener

    1: 有两个地方必须做异常处理,异常类型为IOException 服务器读客户端发来的信息时: LeafTCPClient client = (LeafTCPClient)ar.AsyncState; ...

  2. HDFS中NameNode发生故障没有备份从SecondNameNode恢复

    1.Secondary NameNode目录结构 Secondary NameNode用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照. 在/opt/module/hadoop ...

  3. Appium+Python之生成html测试报告

    思考:测试用例执行后,如何生成一个直观漂亮的测试报告呢? 分析:1.unittest单元测试框架本身带有一个textTestRunner类,可以生成txt文本格式的测试报告,但是页面不够直观 2.我们 ...

  4. PC端实现浏览器点击分享到QQ好友,空间,微信,微博等

    网上现在比较流行的是JIaThis,但是测试的时候,不能分享给QQ好友,一直卡在输入验证码,以下代码亲测有效,可直接使用 <%@ page language="java" c ...

  5. python编程基础之简单购物车

    #good文件夹内容[ ['Iphone7', 5800], ['Coffee', 30], ['疙瘩汤', 10], ['Python Book', 99], ['Bike', 199], ['Vi ...

  6. Anaconda 安装及Python 多版本间切换

    安装 Anaconda 安装anaconda 安装较为简单,这里参考官方文档:https://docs.continuum.io/anaconda/install/linux.html 在文件目录下执 ...

  7. R语言——ifelse函数

    在数据处理中,经常会遇到要对判断结果做处理的情况.if函数是经常遇到的. ifelse(cond,statment1,statment2) 如果cond成立,执行statment1,否则执行statm ...

  8. docker安装各种坑

    今天记录一下之前安装docker遇到的各种坑. 我们从http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/这个网站下载. 下 ...

  9. AIX下的ha高可用集群cluster

    安装ha软件 一.安装软件 最稳定的版本是5.4.0,优先安装稳定版本5.4 安装依赖于包base.data, cluster的man包安装失败原因是缺少base.data包 安装所有cluster. ...

  10. 项目中dubbo的标准配置

    # Spring boot applicationspring: application: name: hello-dubbo-service-user-provider # UserService ...