从基础到重要依次排开.
Table of Contents
1.字段设计
规范整合:https://zhuanlan.zhihu.com/p/83767383
分页id:https://zhuanlan.zhihu.com/p/107939861
1.1精度要求
尽可能小的以业务需要的字段设计精度.
字节:按照UTF-8进行编码,英文占用1字节,中文占用3字节.通常一个字符占用1-4个字节,请根据所需要用到的字节进行精度判断.
1.2尽量使用整数表示字符串
整数查询速度比字符串快,建立索引的速度也比字符串快.主要原因在于,字符型需要转成整数再进行查询,多一层操作.
1.3尽可能会用not null
1.Null 列需要更多的存储空间:需要一个额外字节作为判断是否为 NULL 的标志位.
2.进行比较和计算时会对null值进行处理,可能导致索引失效,类似于count不会计算null的值
3.常说的in null,not in null不会进行索引命中其实是错误的,这里符合复合索引最左匹配原则
1.4定长与非定长的选择
1.varchar为变长,char为定长varchar节省空间,但是在update改变空间长度的时候,会消耗额外的耗时.根据业务需求来存储最合适的长度字段。
char适用:很短,或者所有值都接近同一个长度(如MD5)列经常变更.
varchar适用:字符串列的最大长度比平均长度大很多,列的更新很少
1.5遵循范式要求
尽可能不要在表中建立顾名思义的扩展字段:
比如 ext
、ext_1
、extend_n
,时间一长,好几个这样的字段,即使每一个都有 comment
,也会降低 SQL
的可读性,特别是在构建 SQL
语句的时候。
优先设置占存储空间最小的类型和长度:
合理设置字段的类型和长度,可以节省 MySQL
的表空间,是性能优化的姿势之一。同时,索引列定义空间越大也会导致建立索引的所需空间也越大。应当严禁定义字段,譬如IP
应使用 UNSUGNED
或者 INT
结构类型,在 PHP 中可以使用 long2ip
与 ip2long
函数进行互转
性别应使用 CHAR(1)
,即定长的字符串类型
尽可能避免使用TEXT
、BLOB
、ENUM
数据类型:
MySQL 内存临时表不支持 TEXT
、BLOB
这样的大数据类型,如果查询中包含这样的数据,在排序等操作时,就不能使用内存临时表,必须使用磁盘临时表进行,毋庸置疑会降低查询的效率。MySQL
对索引字段长度是有限制的,TEXT
或 BLOB
类型只能使用前缀索引。
避免ENUM
数据类型:
在 MySQL
中,存储枚举类型的数据在库中,字段列中保存的值实际为整数,特别容易导致开发者混乱,同时在查询使用排序是基于数值整型的,虽然可以使用 ORDER BY FIELD()
, 但是会导致索引失效,尽量避免这么做。
使用TIMESTAMP
与INT
替换DATETIME
存储时间
很明显,TIMESTAMP
与 INT
占 4 位字节,而 DATETIME
占 8 位字节。那么存储时间应该如何选择 TIMESTAMP
与 INT
呢?TIMESTAMP
的可读性高而 INT
的灵活性高,因而经常需要使用计算操作的应当使用 INT
存储,否则使用 TIMESTAMP
。
使用UNSIGNEG
存储非负整数
节省存空间、降低内存使用率、提高读写性能。
禁止敏感数据以明文形式存储
确保信息的安全性,比如密码、隐秘数据等。
2.存储引擎的选择
2.1功能差异
功 能 | MYISAM | Memory | InnoDB | Archive |
存储限制 | 256TB | RAM | 64TB | None |
支持事物 | No | No | Yes | No |
支持全文索引 | Yes | No | No | No |
支持数索引 | Yes | Yes | Yes | No |
支持哈希索引 | No | Yes | No | No |
支持数据缓存 | No | N/A | Yes | No |
支持外键 | No | No | Yes | No |
2.2存储差异
InnoDB存储引擎
InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,InnoDB是默认的MySQL引擎。InnoDB主要特性有:
1、InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句中提供一个类似Oracle的非锁定读。这些功能增加了多用户部署和性能。在SQL查询中,可以自由地将InnoDB类型的表和其他MySQL的表类型混合起来,甚至在同一个查询中也可以混合
2、InnoDB是为处理巨大数据量的最大性能设计。它的CPU效率可能是任何其他基于磁盘的关系型数据库引擎锁不能匹敌的
3、InnoDB存储引擎完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB将它的表和索引在一个逻辑表空间中,表空间可以包含数个文件(或原始磁盘文件)。这与MyISAM表不同,比如在MyISAM表中每个表被存放在分离的文件中。InnoDB表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上
4、InnoDB支持外键完整性约束,存储表中的数据时,每张表的存储都按主键顺序存放,如果没有显示在表定义时指定主键,InnoDB会为每一行生成一个6字节的ROWID,并以此作为主键
5、InnoDB被用在众多需要高性能的大型数据库站点上
InnoDB不创建目录,使用InnoDB时,MySQL将在MySQL数据目录下创建一个名为ibdata1的10MB大小的自动扩展数据文件,以及两个名为ib_logfile0和ib_logfile1的5MB大小的日志文件
MyISAM存储引擎
MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物。MyISAM主要特性有:
1、大文件(达到63位文件长度)在支持大文件的文件系统和操作系统上被支持
2、当把删除和更新及插入操作混合使用的时候,动态尺寸的行产生更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块自动完成
3、每个MyISAM表最大索引数是64,这可以通过重新编译来改变。每个索引最大的列数是16
4、最大的键长度是1000字节,这也可以通过编译来改变,对于键长度超过250字节的情况,一个超过1024字节的键将被用上
5、BLOB和TEXT列可以被索引
6、NULL被允许在索引的列中,这个值占每个键的0~1个字节
7、所有数字键值以高字节优先被存储以允许一个更高的索引压缩
8、每个MyISAM类型的表都有一个AUTO_INCREMENT的内部列,当INSERT和UPDATE操作的时候该列被更新,同时AUTO_INCREMENT列将被刷新。所以说,MyISAM类型表的AUTO_INCREMENT列更新比InnoDB类型的AUTO_INCREMENT更快
9、可以把数据文件和索引文件放在不同目录
10、每个字符列可以有不同的字符集
11、有VARCHAR的表可以固定或动态记录长度
12、VARCHAR和CHAR列可以多达64KB
使用MyISAM引擎创建数据库,将产生3个文件。文件的名字以表名字开始,扩展名之处文件类型:frm文件存储表定义、数据文件的扩展名为.MYD(MYData)、索引文件的扩展名时.MYI(MYIndex)
MEMORY存储引擎
MEMORY存储引擎将表中的数据存储到内存中,未查询和引用其他表数据提供快速访问。MEMORY主要特性有:
1、MEMORY表的每个表可以有多达32个索引,每个索引16列,以及500字节的最大键长度
2、MEMORY存储引擎执行HASH和BTREE缩影
3、可以在一个MEMORY表中有非唯一键值
4、MEMORY表使用一个固定的记录长度格式
5、MEMORY不支持BLOB或TEXT列
6、MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引
7、MEMORY表在所由客户端之间共享(就像其他任何非TEMPORARY表)
8、MEMORY表内存被存储在内存中,内存是MEMORY表和服务器在查询处理时的空闲中,创建的内部表共享
9、当不再需要MEMORY表的内容时,要释放被MEMORY表使用的内存,应该执行DELETE FROM或TRUNCATE TABLE,或者删除整个表(使用DROP TABLE)
2.3选择依据
如果要提供提交、回滚、崩溃恢复能力的事物安全(ACID兼容)能力,并要求实现并发控制,InnoDB是一个好的选择
如果数据表主要用来插入和查询记录,则MyISAM引擎能提供较高的处理效率
如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存中的Memory引擎,MySQL中使用该引擎作为临时表,存放查询的中间结果
如果只有INSERT和SELECT操作,可以选择Archive,Archive支持高并发的插入操作,但是本身不是事务安全的。Archive非常适合存储归档数据,如记录日志信息可以使用Archive
3.索引
3.1索引类型
1.普通索引
最基本的索引,它没有任何限制,用于加速查询
2.唯一索引
索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
3.主键索引
是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。
这里有一个概念,聚簇索引和非聚簇索引,只有主键索引才是聚簇索引.概念:索引上直接绑定数据.详情请见索引数据结构
4.组合索引(复合索引)
指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左匹配原则。
5.全文索引(innodb不支持全文索引,面试的时候如果你是innodb不要犯错)
主要用来查找文本中的关键字,而不是直接与索引中的值相比较。
6.覆盖索引
搜索的字段中包含索引,可以不回表,直接查到数据进行返回.例:select name from students where name = 'test';
7.前缀索引
长文本情况下,可以用文本前xx位创建索引进行前缀索引创建
3.2索引原理
一个没加主键的表,它的数据无序的放置在磁盘存储器上,一行一行的排列的很整齐, 跟我认知中的「表」很接近。如果给表上了主键,那么表在磁盘上的存储结构就由整齐排列的结构转变成了树状结构,也就是上面说的「平衡树」结构,换句话说,就是整个表就变成了一个索引。
这就是所谓的聚集索引,所以一个表只能有一个主键,一个表只能有一个聚集索引
一个表只能有一个主键的,至于平时多个主键的原因是因为联合主键!!!(多个字段一起作为一张表的主键)
主键的主键的作用是保证数据的唯一性和完整性,同时通过主键检索表能够增加检索速度。
3.3索引的数据结构
https://mp.weixin.qq.com/s/jRZMMONW3QP43dsDKIV9VQ
Hash索引.
B+树:为什么使用B树,其实二叉查询树已经够了,但是在数据库中需要考虑到磁盘IO的问题.不可能将整个索引加载到磁盘进行处理,每个树的叶子节点代表一个磁盘页.磁盘IO次数和树的高度有关,与磁盘IO的速度比较,内存比较的速度快非常多.所以树要尽量矮胖.
拓展:B树:B树最大特点:能够在二叉查询树的情况下保持自身的自平衡.使用:MongoDB.文件索引.卫星数据:每个索引都会带有一个数据
查找值为10的情况下,磁盘的IO状态:
如果使用B树
3.4索引的存储结构
使用B+树的索引.每个元素代表一条数据,数据和索引11对应.在磁盘中,每一个节点对应一页.
3.5索引的应用场景
哪些情况需要创建索引
1.主键自动建立唯一索引
2.频繁作为查询的条件的字段应该创建索引
3.查询中与其他表关联的字段,外键关系建立索引
6.单间/组合索引的选择问题,who?(在高并发下倾向创建组合索引)
7.查询中排序的字段,排序字段若通过索引去访问将大大提高排序的速度
8.查询中统计或者分组字段
哪些情况不要创建索引
1.表记录太少
2.经常增删改的表
3.数据重复且分布平均的表字段,因此应该只为经常查询和经常排序的数据列建立索引。
注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
4.频繁更新的字段不适合创建索引
5.Where条件里用不到的字段不创建索引
小tips
1. 当数据多且字段值有相同的值得时候用普通索引。
2. 当字段多且字段值没有重复的时候用唯一索引。
3. 当有多个字段名都经常被查询的话用复合索引。
4. 普通索引不支持空值,唯一索引支持空值。
5. 但是,若是这张表增删改多而查询较少的话,就不要创建索引了,因为如果你给一列创建了索引,那么对该列进行增删改的时候,都会先访问这一列的索引,
6. 若是增,则在这一列的索引内以新填入的这个字段名的值为名创建索引的子集,
7. 若是改,则会把原来的删掉,再添入一个以这个字段名的新值为名创建索引的子集,
8. 若是删,则会把索引中以这个字段为名的索引的子集删掉。
9. 所以,会对增删改的执行减缓速度,
10. 所以,若是这张表增删改多而查询较少的话,就不要创建索引了。
11. 更新太频繁地字段不适合创建索引。
12. 不会出现在where条件中的字段不该建立索引。
3.6聚簇索引与非聚簇索引、复合索引
聚簇索引:
按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,也将聚集索引的叶子节点称为数据页。这个特性决定了索引组织表中数据也是索引的一部分,每张表只能拥有一个聚簇索引。
Innodb通过主键聚集数据,如果没有定义主键,innodb会选择非空的唯一索引代替。如果没有这样的索引,innodb会隐式的定义一个主键来作为聚簇索引。
聚簇索引的优缺点
优点:
1.数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
2.聚簇索引对于主键的排序查找和范围查找速度非常快
缺点:
1.插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
2.更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。
3.二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
非聚簇索引:
在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找。辅助索引叶子节点存储的不再是行的物理位置,而是主键值。通过辅助索引首先找到的是主键值,再通过主键值找到数据行的数据页,再通过数据页中的Page Directory找到数据行。
Innodb辅助索引的叶子节点并不包含行记录的全部数据,叶子节点除了包含键值外,还包含了相应行数据的聚簇索引键。
复合索引
1. 用户可以在多个列上建立索引,这种索引叫做复合索引(组合索引)。
2. 就是几个字段联合在一起组成一个索引.复合索引的创建方法与创建单一索引的方法完全一样。
3. 但复合索引在数据库操作期间所需的开销更小,可以代替多个单一索引。
4. 当表的行数远远大于索引键的数目时,使用这种方式可以明显加快表的查询速度。
3.7索引命中规则
1、如果条件中有 or ,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
2.、like查询是以%开头,索引不会命中
只有一种情况下,只查询索引列,才会用到索引,但是这种情况下跟是否使用%没有关系的,因为查询索引列的时候本身就用到了索引
a.like %keyword 索引失效,使用全表扫描。但可以通过翻转函数+like前模糊查询+建立翻转函数索引=走翻转函数索引,不走全表扫描。如where reverse(code) like reverse('%Code2').反转函数重点!
b.like keyword% 索引有效。
c.like %keyword% 索引失效,也无法使用反向索引。
3. 如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
4. 没有查询条件,或者查询条件没有建立索引
5. 查询条件中,在索引列上使用函数(+, - ,*,/), 这种情况下需建立函数索引
6. 采用 not in, not exist,这里解释一下为什么不走索引,因为在很多场景下,NOT IN或<>两类操作使用二级索引的成本远超于全表扫描的成本,查询优化器按照成本选择"最优执行计划",导致查询不走二级索引。但不能因此就彻底判断NOT IN或<>两类操作不能走索引.
7.最左匹配原则,
8.5.6以上mysql,in ,not in 都会使用索引.
3.8函数索引
建立索引时使用函数,使用函数进行直接查询覆盖.
3.9页分裂
https://zhuanlan.zhihu.com/p/98818611
3.10自增id的缺陷
环境:mysql / innodb
前提:单机/单数据库项目,数据量小,使用mysql自增ID
缺陷:说服力从高到底
1. 数据量大 + 没有合理设置步长,导致自增id用完后,mysql读写功能停止,解决办法:重制自增 DBCC CHECKIDENT(testaaa,reseed,0)
2. **扩展性低**,分库分表 / 跨机器 / 跨机房部署的环境下,自增id无法保证全局唯一性,(云端早期跨机房部署国外业务,出现两个不同国家用户的id相同)
3. **性能低**,每获取一次自增id,必须在业务执行中触发一次mysql的写操作。请求量高的场景会使mysql宕机。
4. **业务设计不友好** 如果业务b依赖业务a的id做表关联,则必须等到业务a插入完成后才可以拿到id(当然一般不建议使用id做表关联,不利于重置id)
4.SQL优化
https://www.jianshu.com/p/2bca7e9c2ad0
回表查询:使用非聚簇索引的时候,非聚簇索引使用保存的是聚簇索引的主键,所以查询完毕之后会再对聚簇索引进行查询.这样的查询我们成为回表.
explain语句:
显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。
使用方法,在select语句前加上explain就可以了:
如:explain select surname,first_name form a,b where a.id=b.id
sql优化大多数情况下是索引没有命中,导致全表扫描从而导致sql变慢,针对这个操作,需要在书写过程中多用explain语句对库进行更新优化.
5.锁与事物
总结参考于:https://www.cnblogs.com/kismetv/p/10331633.html.
首先看一下sql的运行规则
1.事务的ACID性
Atomicity:原子性,原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做;如果事务中一个sql语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。
主要使用undoLog进行执行保证.
Consistency:一致性,持久性是指事务一旦提交,它对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
主要使用redoLog进行保证.
I:隔离性,主要由各种事务进行保证.锁机制,mvcc
D:持久性
2.并发带来的问题
脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据).
不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据.
幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,这种现象称为幻读。不可重复读与幻读的区别可以通俗的理解为:前者是数据变了,后者是数据的行数变了.
3.事务隔离级别:
4.MVCC
RR解决脏读、不可重复读、幻读等问题,使用的是MVCC:MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议。下面的例子很好的体现了MVCC的特点:在同一时刻,不同的事务读取到的数据可能是不同的(即多版本)——在T5时刻,事务A和事务C可以读取到不同版本的数据。
6.数据库水平拆分与垂直拆分、分库分表
- 历史表:按时间拆分历史表出去,降低数据量,这个以前比较常见,其实也是一种特殊的水平拆分,对业务有侵入性
- 垂直拆分:按列,将上百列的宽表拆分成多个列少(也就是每条记录数据量小)的表,不降低记录数,但是降低整个表的数据量和索引量大小
- 水平拆分:按某个或某些个列的值哈希后,均匀的将数据拆分到多个同样的库or表里,这样就直接降低了单库单表的数据量,比如说拆分成1024个子表,就可以将单表的数据量降低3个数量级,原来一亿的表,现在单表10万数据,在单表上做复杂操作都可以很快速了。这样的缺点就是,原来只需要操作一个表,现在操作之前需要先知道要操作那张表,比如一个用户表,按uid分表:原来的SQL1: select * from users where uid=1025,现在得先知道uid是1025,然后知道1025%1024==1,SQL就变成了SQL2: select * from users_0001 where uid=1025,看起来对业务也是于侵入型的。怎么能对业务变得透明,这就需要一个中间件,帮我们自动的把SQL1变成SQL2,从而使得我们分不分库、分不分表,分多少个,代码都差不多,不用太多修改。
- 读写分离:比如MySQL的TPS/QPS都已经很高了,几千上万,而且已经做了1主3从的时候,我们希望这4个实例都能分担一些压力,特别是读多写少的情况,如果把读的压力大家平分,就可以降低主库的读压力,让主库关注与写。这时候也需要一个中间件来把数据请求路由到不同的库上。
垂直切分除了用于分解单库单表的压力,也用于实现冷热分离,也就是根据数据的活跃度进行拆分,因为对拥有不同活跃度的数据的处理方式不同。
这里我们再举一个例子:在微博系统的设计中,一个微博对象包括文章标题、作者、分类、创建时间等属性字段,这些字段的变化频率低,查询次数多,叫作冷数据。而博客的浏览量、回复数、点赞数等类似的统计信息,或者别的变化频率比较高的数据,叫作活跃数据或者热数据。
我们把冷热数据分开存放,就叫作冷热分离,在MySQL的数据库中,冷数据查询较多,更新较少,适合用MyISAM引擎,而热数据更新比较频繁,适合使用InnoDB存储引擎,这也是垂直拆分的一种。
当我们使用读写分离、缓存后,数据库的压力还是很大的时候,这就需要使用到数据库拆分了.
数据库拆分简单来说,就是指通过某种特定的条件,按照某个维度,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面以达到分散单库(主机)负载的效果。
切分模式: 垂直(纵向)拆分、水平拆分。
垂直拆分:
专库专用
一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如下图:
优点:
1. 拆分后业务清晰,拆分规则明确。
2. 系统之间整合或扩展容易。
3. 数据维护简单。
缺点:
1. 部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。
2. 受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。
3. 事务处理复杂。
水平拆分
垂直拆分后遇到单机瓶颈,可以使用水平拆分。相对于垂直拆分的区别是:垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中。
相对于垂直拆分,水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式,如图:
优点:
1. 不存在单库大数据,高并发的性能瓶颈。
2. 对应用透明,应用端改造较少。
3. 按照合理拆分规则拆分,join操作基本避免跨库。
4. 提高了系统的稳定性跟负载能力。
缺点:
1. 拆分规则难以抽象。
2. 分片事务一致性难以解决。
3. 数据多次扩展难度跟维护量极大。
4. 跨库join性能较差。
拆分原则
1. 尽量不拆分,架构是进化而来,不是一蹴而就。(SOA)
2. 最大可能的找到最合适的切分维度。
3. 由于数据库中间件对数据Join 实现的优劣难以把握,而且实现高性能难度极大,业务读取 尽量少使用多表Join -尽量通过数据冗余,分组避免数据垮库多表join。
4. 尽量避免分布式事务。
5. 单表拆分到数据1000万以内。
切分方案
范围、枚举、时间、取模、哈希、指定等
7.集群
读写分离,主从库.
双写问题
额外知识:
ASCII码:
一个bai英文字母(不分大小写)du占一个字节的空间,一个中文汉字占zhi两个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。如一个ASCII码就是一个字节。
UTF-8编码:
一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。
Unicode编码:
一个英文等于两个字节,一个中文(含繁体)等于两个字节。
创作不易,欢迎评论指出各种不对的地方.
也感谢各位捧场支持.