数据库相关
1.InnoDB的日志
InnoDB有很多日志,日志中有2个概念需要分清楚,逻辑日志和物理日志.
1.1 逻辑日志
有关操作的信息日志成为逻辑日志.
比如,插入一条数据,undo逻辑日志的格式大致如下:
<Ti,Qj,delete,U> Ti表示事务id,U表示Undo信息,Qj表示某次操作的唯一标示符undo日志总是这样:
1). insert操作,则记录一条delete逻辑日志.
2). delete操作,则记录一条insert逻辑日志.
3). update操作,记录相反的update,将修改前的行改回去.1.2 物理日志
新值和旧值的信息日志称为物理日志. <Ti,Qj,V> 物理日志binlog(二进制日志)就是典型的逻辑日志,而事务日志(redo log)则记录的物理日志,他们的区别是什么呢?
redo log 是在存储引擎层产生的,binlog是在数据库上层的一种逻辑日志,任何存储引擎均会产生binlog.
binlog记录的是sql语句, 重做日志则记录的是对每个页的修改.
写入的时间点不一样. binlog是在事务提交后进行一次写入,redo log在事务的进行中不断的被写入.
redo log是等幂操作(执行多次等于执行一次,redo log记录<T0,A,950>记录新值,执行多少次都一样),binlog不一样;
1.3 日志种类
错误日志:记录出错信息,也记录一些警告信息或者正确的信息。
查询日志:记录所有对数据库请求的信息,不论这些请求是否得到了正确的执行。
慢查询日志:设置一个阈值,将运行时间超过该值的所有SQL语句都记录到慢查询的日志文件中。 二进制日志:记录对数据库执行更改的所有操作。
中继日志、事务日志等。
1.4 总结
1, redo log(事务日志)保证事务的原子性和持久性(物理日志)
2, undo log保证事务的一致性,InnoDB的MVCC(多版本并发控制)也是用undo log来实现的(逻辑日志).
3, redo log中带有有checkPoint,用来高效的恢复数据.
4, 物理日志记录的是修改页的的详情,逻辑日志记录的是操作语句. 物理日志恢复的速度快于逻辑日志.
2.事务的实现原理
事务的作用: 事务会把数据库从一种一致的状态转换为另一种一致状态。
事务的机制通常被概括为“ACID”原则即原子性(A)、一致性(C)、隔离性(I)和持久性(D)。
原子性:构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不执行。
一致性:数据库在事务执行前后状态都必须是稳定的。
隔离性:事务之间不会相互影响。
持久性:事务执行成功后必须全部写入磁盘。
2.1 事务的隔离性由存储引擎的锁来实现
数据库事务会导致脏读、不可重复读和幻影读等问题。
1)脏读:事务还没提交,他的修改已经被其他事务看到。
2)不可重复读:同一事务中两个相同SQL读取的内容可能不同。两次读取之间其他事务提交了修改可能会造成读取数据不一致。
3)幻影数据:同一个事务突然发现他以前没发现的数据。和不可重复读很类似,不过修改数据改成增加数据。
InnoDB提供了四种不同级别的机制保证数据隔离性。
不同于MyISAM使用表级别的锁,InnoDB采用更细粒度的行级别锁,提高了数据表的性能。InnoDB的锁通过锁定索引来实现,如果查询条件中有主键则锁定主键,如果有索引则先锁定对应索引然后再锁定对应的主键(可能造成死锁),如果连索引都没有则会锁定整个数据表。4种隔离级别:
1) READ UNCOMMITTED(未提交读)
事务中的修改,即使没有提交,对其它事务也是可见的. 脏读(Dirty Read).
2) READ COMMITTED(提交读)
一个事务开始时,只能"看见"已经提交的事务所做的修改. 这个级别有时候也叫不可重复读(nonrepeatable read).
3) REPEATABLE READ(可重复读)
该级别保证了同一事务中多次读取到的同样记录的结果是一致的. 但理论上,该事务级别还是无法解决另外一个幻读的问题(Phantom Read).
幻读: 当某个事务读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录.当之前的事务再次读取该范围时,会产生幻行.(Phantom Row).
幻读的问题理应由更高的隔离级别来解决,但mysql和其它数据库不一样,它同样在可重复读的隔离级别解决了这个问题.
mysql的可重复读的隔离级别解决了"不可重复读"和“幻读”2个问题.
而oracle数据库,可能需要在“SERIALIZABLE”事务隔离级别下才能解决幻读问题.
mysql默认的隔离级别也是:REPEATABLE READ(可重复读)
4) SERIALIZABLE (可串行化)
强制事务串行执行,避免了上面说到的 脏读,不可重复读,幻读 三个的问题.
2.2 原子性和持久性的实现
redo log 称为重做日志(也叫事务日志),用来保证事务的原子性和持久性.
redo恢复提交事务修改的页操作,redo是物理日志,页的物理修改操作.当提交一个事务时,实际上它干了如下2件事:
一: InnoDB存储引擎把事务写入日志缓冲(log buffer),日志缓冲把事务刷新到事务日志.
二: InnoDB存储引擎把事务写入缓冲池(Buffer pool).这里有个问题, 事务日志也是写磁盘日志,为什么不需要双写技术?
因为事务日志块的大小和磁盘扇区的大小一样,都是512字节,因此事务日志的写入可以保证原子性,不需要doublewrite技术重做日志缓冲是由每个为512字节大小的日志块组成的. 日志块分为三部分: 日志头(12字节),日志内容(492字节),日志尾(8字节).
2.3 一致性的实现
undo log 用来保证事务的一致性. undo 回滚行记录到某个特定版本,undo 是逻辑日志,根据每行记录进行记录.
undo 存放在数据库内部的undo段,undo段位于共享表空间内.
undo 只把数据库逻辑的恢复到原来的样子.undo日志除了回滚作用之外, undo 实现MVCC(多版本并发控制),读取一行记录时,发现事务锁定,通过undo恢复到之前的版本,实现非锁定读取.
myisam引擎不支持事务, innodb和BDB引擎支持
3. 索引有什么用
作用:索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度。索引包含由表或视图中的一列或多列生成的键。这些键存储在一个结构(B树)中,使数据库可以快速有效地查找与键值关联的行。
设计良好的索引可以减少磁盘 I/O 操作,并且消耗的系统资源也较少,从而可以提高查询性能。
一般来说,应该在这些列 上创建索引,例如:
在经常需要搜索的列上,可以加快搜索的速度;
在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
在经常用在连接的列上,这 些列主要是一些外键,可以加快连接的速度;
在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
在经常需要排序的列上创 建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。索引的缺点:
第一,创建索引和维护索引要耗费时间,这种时间随着数据 量的增加而增加。
第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
4.数据库优化相关
临时表在如下几种情况被创建(临时表会消耗性能):
1、如果group by 的列没有索引,必产生内部临时表。
2、如果order by 与group by为不同列时,或多表联查时order by ,group by 包含的列不是第一张表的列,将会产生临时表
3、distinct 与order by 一起使用可能会产生临时表
4、如果使用SQL_SMALL_RESULT,MySQL会使用内存临时表,除非查询中有一些必须要把临时表建立在磁盘上.
5、union合并查询时会用到临时表
6、某些视图会用到临时表,如使用temptable方式建立,或使用union或聚合查询的视图 想确定查询是否需要临时表,可以用EXPLAIN查询计划,并查看Extra列,看是否有Using temporary.建表: 表结构的拆分,如核心字段都用int,char,enum等定长结构
非核心字段,或用到text,超长的varchar,拆出来单放一张表.
建索引: 合理的索引可以减少内部临时表
写语句: 不合理的语句将导致大量数据传输以及内部临时表的使用表的优化与列类型选择
表的优化:
1: 定长与变长分离
如 id int, 占4个字节, char(4) 占4个字符长度,也是定长, time
即每一单元值占的字节是固定的.
核心且常用字段,宜建成定长,放在一张表.
而varchar, text,blob,这种变长字段,适合单放一张表, 用主键与核心表关联起来.
2:常用字段和不常用字段要分离.
需要结合网站具体的业务来分析,分析字段的查询场景,查询频度低的字段,单拆出来.
3:合理添加冗余字段.列选择原则:
1:字段类型优先级 整型 > date,time > enum,char > varchar > blob列的特点分析:
整型: 定长,没有国家/地区之分,没有字符集的差异
time定长,运算快,节省空间. 考虑时区,写sql时不方便 where > ‘2005-10-12’;
enum: 能起来约束值的目的, 内部用整型来存储,但与char联查时,内部要经历串与值的转化 Char 定长, 考虑字符集和(排序)校对集 varchar, 不定长 要考虑字符集的转换与排序时的校对集,速度慢.相比于char增加了一个长度标识,处理时需要多运算一次。 text/Blob 无法使用内存临时表附: 关于date/time的选择,明确意见 http://www.xaprb.com/blog/2014/01/30/timestamps-in-mysql/
2: 够用就行,不要慷慨 (如smallint,varchar(N))
原因: 大的字段浪费内存,影响速度
以年龄为例 tinyint unsigned not null ,可以存储255岁,足够. 用int浪费了3个字节 以varchar(10) ,varchar(300)存储的内容相同, 但在表联查时,varchar(300)要花更多内存3: 尽量避免用NULL()
原因: NULL不利于索引,要用特殊的字节来标注. 每一行多了一个字节在磁盘上占据的空间其实更大.Enum列的说明
1: enum列在内部是用整型来储存的
2: enum列与enum列相关联速度最快
3: enum列比(var)char 的弱势---在碰到与char关联时,要转化. 要花时间.
4: 优势在于,当char非常长时,enum依然是整型固定长度.当查询的数据量越大时,enum的优势越明显.
5: enum与char/varchar关联 ,因为要转化,速度要比enum->enum,char->char要慢,但有时也这样用-----就是在数据量特别大时,可以节省IO.SQL语句优化
1)应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
2)应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
3)很多时候用 exists 代替 in 是一个好的选择
4)用Where子句替换HAVING 子句 因为HAVING 只会在检索出所有记录之后才对结果集进行过滤explain出来的各种item的意义;
select_type
表示查询中每个select子句的类型
type
表示MySQL在表中找到所需行的方式,又称“访问类型”
possible_keys
指出MySQL能使用哪个索引在表中找到行,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用
key
显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL
key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度
ref
表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
Extra
包含不适合在其他列中显示但十分重要的额外信息profile的意义以及使用场景;
查询到 SQL 会执行多少时间, 并看出 CPU/Memory 使用量, 执行过程中 Systemlock, Table lock 花多少时间等等
索引优化策略
1 索引类型
1.1 B-tree索引
注: 名叫btree索引,大的方面看,都用的平衡树,但具体的实现上, 各引擎稍有不同,比如,严格的说,NDB引擎,使用的是T-tree,Myisam,innodb中,默认用B-tree索引,但抽象一下---B-tree系统,可理解为”排好序的快速查找结构”.1.2 hash索引
在memory表里,默认是hash索引, hash的理论查询时间复杂度为O(1)疑问: 既然hash的查找如此高效,为什么不都用hash索引?
答:
1)hash函数计算后的结果,是随机的,如果是在磁盘上放置数据,比主键为id为例, 那么随着id的增长, id对应的行,在磁盘上随机放置.
2)不法对范围查询进行优化.
3)无法利用前缀索引. 比如 在btree中, field列的值“hellopworld”,并加索引 查询 xx=helloword,自然可以利用索引, xx=hello,也可以利用索引. (左前缀索引) 因为hash(‘helloword’),和hash(‘hello’),两者的关系仍为随机
4)排序也无法优化.
5)必须回行.就是说 通过索引拿到数据位置,必须回到表中取数据2 btree索引的常见误区
2.1 在where条件常用的列上都加上索引
例: where cat_id=3 and price>100 ; //查询第3个栏目,100元以上的商品
误: cat_id上,和, price上都加上索引.
错: 只能用上cat_id或Price索引,因为是独立的索引,同时只能用上1个.2.2 在多列上建立索引后,查询哪个列,索引都将发挥作用
误: 多列索引上,索引发挥作用,需要满足左前缀要求.在多列上建立索引后,查询语句发挥作用的索引:
为便于理解, 假设ABC各10米长的木板, 河面宽30米.
全值索引是则木板长10米,
Like,左前缀及范围查询, 则木板长6米,
自己拼接一下,能否过河对岸,就知道索引能否利用上.
如上例中, where a=3 and b>10, and c=7,
A板长10米,A列索引发挥作用
A板正常接B板, B板索引发挥作用
B板短了,接不到C板, C列的索引不发挥作用.
索引应用举例:
innodb的主索引文件上 直接存放该行数据,称为聚簇索引,次索引指向对主键的引用
myisam中, 主索引和次索引,都指向物理行(磁盘位置).注意: 对innodb来说,
1: 主键索引 既存储索引值,又在叶子中存储行的数据
2: 如果没有主键, 则会Unique key做主键
3: 如果没有unique,则系统生成一个内部的rowid做主键.
4: 像innodb中,主键的索引结构中,既存储了主键值,又存储了行数据,这种结构称为”聚簇索引”聚簇索引
优势: 根据主键查询条目比较少时,不用回行(数据就在主键节点下)
劣势: 如果碰到不规则数据插入时,造成频繁的页分裂.
聚簇索引的主键值,应尽量是连续增长的值,而不是要是随机值,(不要用随机字符串或UUID)否则会造成大量的页分裂与页移动.高性能索引策略
对于innodb而言,因为节点下有数据文件,因此节点的分裂将会比较慢.
对于innodb的主键,尽量用整型,而且是递增的整型.
如果是无规律的数据,将会产生的页的分裂,影响速度.索引覆盖:
索引覆盖是指 如果查询的列恰好是索引的一部分,那么查询只需要在索引文件上进行,不需要回行到磁盘再找数据.这种查询速度非常快,称为”索引覆盖”
理想的索引
1:查询频繁 2:区分度高 3:长度小 4: 尽量能覆盖常用查询字段.
注:
索引长度直接影响索引文件的大小,影响增删改的速度,并间接影响查询速度(占用内存多). 针对列中的值,从左往右截取部分,来建索引
1: 截的越短, 重复度越高,区分度越小, 索引效果越不好
2: 截的越长, 重复度越低,区分度越高, 索引效果越好,但带来的影响也越大--增删改变慢,并间接影响查询速度.所以, 我们要在 区分度 + 长度 两者上,取得一个平衡.
惯用手法: 截取不同长度,并测试其区分度,
select count(distinct left(word,6))/count(*) from dict;对于一般的系统应用: 区别度能达到0.1,索引的性能就可以接受.
对于左前缀不易区分的列 ,建立索引的技巧:如 url列
http://www.baidu.com
http://www.zixue.it
列的前11个字符都是一样的,不易区分, 可以用如下2个办法来解决
1: 把列内容倒过来存储,并建立索引
Moc.udiab.www//:ptth
Ti.euxiz.www//://ptth
这样左前缀区分度大,
2: 伪hash索引效果
同时存 url_hash列多列索引 多列索引的考虑因素---列的查询频率、列的区分度。
索引与排序
排序可能发生2种情况:
1: 对于覆盖索引,直接在索引上查询时,就是有顺序的, using index
2: 先取出数据,形成临时表做filesort(文件排序,但文件可能在磁盘上,也可能在内存中)我们的争取目标-----取出来的数据本身就是有序的! 利用索引来排序.
重复索引与冗余索引
重复索引: 是指 在同1个列(如age), 或者 顺序相同的几个列(age,school), 建立了多个索引, 称为重复索引, 重复索引没有任何帮助,只会增大索引文件,拖慢更新速度, 去掉.
冗余索引:是指2个索引所覆盖的列有重叠,称为冗余索引
比如x,m,列,加索引index x(x),index xm(x,m)
x,xm索引, 两者的x列重叠了, 这种情况,称为冗余索引.
甚至可以把 index mx(m,x) 索引也建立, mx, xm 也不是重复的,因为列的顺序不一样.索引碎片与维护
在长期的数据更改过程中, 索引文件和数据文件,都将产生空洞,形成碎片.
我们可以通过一个nop操作(不产生对数据实质影响的操作), 来修改表.
比如: 表的引擎为innodb , 可以 alter table xxx engine innodb
optimize table 表名,也可以修复.注意: 修复表的数据及索引碎片,就会把所有的数据文件重新整理一遍,使之对齐.
这个过程,如果表的行数比较大,也是非常耗费资源的操作.所以,不能频繁的修复.如果表的Update操作很频率,可以按周/月,来修复.
如果不频繁,可以更长的周期来做修复.
数据库相关面试题
1. drop,delete与truncate的区别
drop直接删掉表 truncate删除表中数据,再插入时自增长id又从1开始 delete删除表中数据,可以加where字句。
(1) DELETE语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。
(2) 表和索引所占空间。当表被TRUNCATE 后,这个表和索引所占用的空间会恢复到初始大小,而DELETE操作不会减少表或索引所占用的空间。drop语句将表所占用的空间全释放掉。
(3) 一般而言,drop > truncate > delete
(4) 应用范围。TRUNCATE 只能对TABLE;DELETE可以是table和view
(5) TRUNCATE 和DELETE只删除数据,而DROP则删除整个表(结构和数据)。
(6) truncate与不带where的delete :只删除数据,而不删除表的结构(定义)drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数将被保留,但其状态会变为:invalid。
(7) delete语句为DML(data maintain Language),这个操作会被放到 rollback segment中,事务提交后才生效。如果有相应的 tigger,执行的时候将被触发。
(8) truncate、drop是DLL(data define language),操作立即生效,原数据不放到 rollback segment中,不能回滚
(9) 在没有备份情况下,谨慎使用 drop 与 truncate。要删除部分数据行采用delete且注意结合where来约束影响范围。回滚段要足够大。要删除表用drop;若想保留表而将表中数据删除,如果于事务无关,用truncate即可实现。如果和事务有关,或老师想触发trigger,还是用delete。
(10) Truncate table 表名 速度快,而且效率高,因为:
truncate table 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
(11) TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。
(12) 对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。
2.数据库范式
1 第一范式(1NF)
在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。
所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。简而言之,第一范式就是无重复的列。
2 第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被惟一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。这个惟一属性列被称为主关键字或主键、主码。 第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的惟一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。
3 第三范式(3NF)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性。(我的理解是消除冗余)
3.MySQL的复制原理以及流程
基本原理流程,3个线程以及之间的关联;
1. 主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlog中;
2. 从:io线程——在使用start slave 之后,负责从master上拉取 binlog 内容,放进 自己的relay log中;
3. 从:sql执行线程——执行relay log中的语句;
4.MySQL中myisam与innodb的区别,至少5点
1>.InnoDB支持事物,而MyISAM不支持事物
2>.InnoDB支持行级锁,而MyISAM支持表级锁
3>.InnoDB支持MVCC, 而MyISAM不支持
4>.InnoDB支持外键,而MyISAM不支持
5>.InnoDB不支持全文索引,而MyISAM支持。
5.innodb引擎的4大特性
插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)
6.myisam和innodb 2者selectcount(*)哪个更快,为什么
myisam更快,因为myisam内部维护了一个计数器,可以直接调取。
7.MySQL中varchar与char的区别以及varchar(50)中的50代表的涵义
(1)、varchar与char的区别
char是一种固定长度的类型,varchar则是一种可变长度的类型
(2)、varchar(50)中50的涵义
最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存,因为order by col采用fixed_length计算col长度(memory引擎也一样)
(3)、int(20)中20的涵义 是指显示字符的长度
但要加参数的,最大为255,比如它是记录行数的id,插入10笔资料,它就显示00000000001 ~~~00000000010,当字符的位数超过11,它也只显示11位,如果你没有加那个让它未满11位就前面加0的参数,它不会在前面加0 20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;
(4)、mysql为什么这么设计
对大多数应用没有意义,只是规定一些工具用来显示字符的个数;int(1)和int(20)存储和计算均一样;
8.开放性问题:
一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录。
1、如果A表TID是自增长,并且是连续的,B表的ID为索引
select * from a,b where a.tid = b.id and a.tid>500000 limit 200;
2、如果A表的TID不是连续的,那么就需要使用覆盖索引.TID要么是主键,要么是辅助索引,B表ID也需要有索引。
select * from b , (select tid from a limit 50000,200) a where b.id = a .tid;
9.mysql数据库引擎MyISAM和InnoDB的区别
10.MySql 表中允许有多少种 TRIGGERS?
在 MySql 表中允许有六种触发器,如下:
·BEFORE INSERT
·AFTER INSERT
·BEFORE UPDATE
·AFTER UPDATE
·BEFORE DELETE
·AFTER DELETE
作者:秋风悲画扇