B-TREE 和 B+-TREE 区别
B-TREE:所有节点都存储数据,即所有节点的数据结构相同。 B+-TREE:只有叶节点存储数据,其他节点存储键值。
InnoDB MyISAM 区别
用MyISAM建表时可以不设主键。
InnoDB建索引树时必须按主键排序,故必须有主键。建表时若不指定主键,InnoDB选择可作唯一标识的列为主键。若无符合条件的列,则自动生成隐含字段作为主键,6字节。
MyISAM是非聚类的,其叶节点只存储Primary Key和数据的地址。
InnoDB是聚类的,其叶节点存储完整的数据。
InnoDB的辅助索引的树,只存储辅助索引和主键。因此搜索时,先根据辅助索引找到对应主键,再搜索主键对应的数据。
优化
考虑到MyISAM和InnoDB的不同性质,(在游戏业务中)可把业务分为两类:第一,访问量大且聚集在对当日数据的查询,第二,访问量较小且散布在历史数据的查询。
第一种情况适用InnoDB,因为InnoDB建的树是聚类的,其查找效率高,能满足大量访问。不过由于它的数据都存在叶节点,故这棵树会相对较大,但是相对于要管理大量历史数据的情况,只管理当日生成的数据所占的磁盘空间相对小,故问题不大。
第二种情况,在访问量不大,但要管理庞大的历史数据的情况下,可以用MyISAM。MyISAM的查询效率相对低点,不过对于访问量不大的情况已经足够。MyISAM的非聚类树的叶节点只存储键值和数据的地址,故树所占空间相对小。 查询中能不用表达式或函数就不用,因为某一列用表达式或函数时,mysql就不会对该列用索引搜索,进而影响后面的索引。如
SELECT * FROM employees.titles
WHERE emp_no='10001'
AND left(title, 6)='Senior';
最好不要用left()函数,应该改为
SELECT * FROM employees.titles
WHERE emp_no='10001'
AND title LIKE 'Senior%'
这样查询速度会提升。下图可见MySQL执行上面两条查询语句所耗的时间:
再如,把<喎?"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> SELECT * FROM employees.titles WHERE emp_no - 1='10000';
改为
SELECT * FROM employees.titles WHERE emp_no='10001';
能提升查询速度。(常量运算尽量先自己算好,转为无表达式的查询语句,再查询)
InnoDB主键不宜过长,因为所有辅助索引都使用主键,过长会导致辅助索引的树过大。 用非单调字段作为InnoDB主键不好,因为频繁地插入删除会导致索引树的频繁分裂与合并。 若你会对某个属性进行频繁查找,可将其设为辅助索引(SECONDARY KEY)。 查询条件用到了索引中列的精确匹配,但是中间某个条件未提供。
例如有如下表
CREATE TABLE titles (
emp_no INT NOT NULL,
title VARCHAR(50) NOT NULL,
from_date DATE NOT NULL,
to_date DATE,
PRIMARY KEY (emp_no,title, from_date)
)
;
当执行
EXPLAIN SELECT * FROM employees.titles
WHERE emp_no='10001'
AND from_date='1986-06-26';
后,可见查询只用到了索引第一个属性emp_no,而from_date并未用到(key_len只有4. 而整个primary key的长度为59):
为提升效率,除了增加辅助索引
,还可以用“隔离列”的方法:
首先查找中间的属性title有什么值,得到'Senior Engineer', 'Staff', 'Engineer', 'Senior Staff', 'Assistant Engineer', 'Technique Leader', 'Manager'。那就把上面查询改为
SELECT * FROM employees.titles
WHERE emp_no='10001' AND title IN ('Senior Engineer', 'Staff', 'Engineer', 'Senior Staff', 'Assistant Engineer', 'Technique Leader', 'Manager') AND from_date='1986-06-26';
给索引中间“填上坑”。
下图给出“未填坑”和“填坑”后的时间比较,可见“填坑”后是快了点。这适用在title属性的值不会太多的情况。如果通过先比较emp_no得到大量的数据,再从中筛选得到想要的from_date,这就会比“隔离列”慢很多。
创建表的时候把属性设为NOT NULL,这样数据库在搜索时就不用检查其是否为NULL。 尽量不要 SELECT *,而是指定要选哪一列。即选取列的数量尽可能少。
const变量存储位置
编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高
struct & class
C++中的struct是对C中的struct的扩充。和class一样,struct有自己的成员函数、构造函数和析构函数,能继承,能实现多态。
区别:
默认继承方式不一样。class默认继承方式为private,struct默认继承方式为public;
访问方式不同。class默认成员为private,struct默认其数据为public;
概念上的区别:
class对应于对象,其包含成员变量;
struct对应于数据结构,其包含数据。
virtual 析构函数
析构函数设为virtual,当父类指针指向new 子类时,delete父指针,会自动识别调用子类析构函数,否则只会调用父类析构函数。
函数名 & 函数签名
函数名:函数的名称
函数签名:包括函数名、参数类型、函数所在的类和名称空间及其他信息
数组指针 & 指针数组
数组指针:
int (*p)[4]; // 由4个元素所组成的数组指针
int a[3][4];
p = a; // p + 1指向的是数组第1行(从0数起)
int* p[4]; // 是指针数组
指针函数&函数指针
指针函数:返回一个指针的函数
void *GetGate(int ID)
函数指针:指向函数的指针包含了函数的地址,可通过它来调用函数
int (*fptr)(int ID);
字节对齐
class A {
int x;
char ch[5];
int get() { return x; }
};
sizeof(A) = 12
长度都是4字节的倍数
CPU每个时钟从内存读取4字节。若存储的数据跨字节,如double类型,则要用两个clock读取,降低效率。(觉得是因为,在32位机器中,每个寄存