- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Mysql临时表及分区表区别详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
临时表与内存表 。
内存表,指的是使用memory引擎的表,建表语法是create table … engine=memory。这种 表的数据都保存在内存里,系统重启的时候会被清空,但是表结构还在。除了这两个特性看 上去比较“奇怪”外,从其他的特征上看,它就是一个正常的表 。
临时表,可以使用各种引擎类型 。如果是使用innodb引擎或者myisam引擎的临时表,写 数据的时候是写到磁盘上的。当然,临时表也可以使用memory引擎.
临时表特性 。
由于临时表只能被创建它的session访问,所以在这个session结束的时候,会自动删除临时表。 也正是由于这个特性,临时表就特别适合join优化这种场景.
create temporary table temp_t like t1; alter table temp_t add index(b); insert into temp_t select * from t2 where b>=1 and b<=2000; select * from t1 join temp_t on (t1.b=temp_t.b),
不同session的临时表是可以重名的,如果有多个session同时执行join优化,不需要担心表名重复导致建表失败的问题。不需要担心数据删除问题。如果使用普通表,在流程执行过程中客户端发生了异常断开,或者数据库发生异常重启,还需要专门来清理中间过程中生成的数据表。而临时表由于会自动回收,所以不需要这个额外的操作。临时表的应用 。
分库分表系统的跨库查询 。
一般分库分表的场景,就是要把一个逻辑上的大表分散到不同的数据库实例上。比如。将一个大 表ht,按照字段f,拆分成1024个分表,然后分布到32个数据库实例上.
分区key的选择是以“减少跨库和跨表查询”为依据的。如果大部分的语句都会包 含f的等值条件,那么就要用f做分区键。这样,在proxy这一层解析完sql语句以后,就能确定将这条语句路由到哪个分表做查询。 比如 。
select v from ht where f=n,
这时,我们就可以通过分表规则(比如,n%1024)来确认需要的数据被放在了哪个分表上。这种语句只需要访问一个分表,是分库分表方案最欢迎的语句形式了.
但是,如果这个表上还有另外一个索引k,并且查询语句是这样的:
select v from ht where k >= m order by t_modified desc limit 100,
这时候,由于查询条件里面没有用到分区字段f,只能到所有的分区中去查找满足条件的所有 行,然后统一做order by 的操作。这种情况下,有两种比较常用的思路:
在proxy层的进程代码中实现排序,对proxy端的压力比较大,尤其是很容易出现内存不够用和cpu瓶颈的问题.
把各个分库拿到的数据,汇总到一个mysql实例的一个表中,然后在这个汇总实例上做逻辑操作.
在汇总库上创建一个临时表temp_ht,表里包含三个字段v、k、t_modifified; 。
在各个分库上执行 。
select v,k,t_modified from ht_x where k >= m order by t_modified desc limit 100,
把分库执行的结果插入到temp_ht表中; 。
执行 。
select v from temp_ht order by t_modified desc limit 100,
为什么临时表可以重名 。
create temporary table temp_t(id int primary key)engine=innodb,
执行这个语句的时候,mysql要给这个innodb表创建一个frm文件保存表结构定义,还要有地方保存表数据.
这个frm文件放在临时文件目录下,文件名的后缀是.frm,前缀是“#sql{进程id}_{线程id}_序列 号”。你可以使用select @@tmpdir命令,来显示实例的临时文件目录.
这个进程的进程号是1234,session a的线程id是4,session b的线程id是5。所以session a和session b创建的临时表,在磁盘上的文件不会重名 。
mysql维护数据表,除了物理上要有文件外,内存里面也有一套机制区别不同的表,每个表都对应一个table_def_key。 对于临时表,table_def_key在“库名+表名”基础上,又加入了“server_id+thread_id”.
也就是说,session a和sessionb创建的两个临时表t1,它们的table_def_key不同,磁盘文件名 也不同,因此可以并存.
分区表的引擎层行为 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
ate
table
`t` (
`ftime` datetime
not
null
,
`c`
int
(11)
default
null
,
key
(`ftime`)
) engine=innodb
default
charset=latin1
partition
by
range (
year
(ftime))
û ॔ګդᎱ
b
(partition p_2017
values
less than (2017) engine = innodb,
partition p_2018
values
less than (2018) engine = innodb,
partition p_2019
values
less than (2019) engine = innodb,
partition p_others
values
less than maxvalue engine = innodb);
insert
into
t
values
(
'2017-4-1'
,1),(
'2018-4-1'
,1);
|
初始化表的时候,只插入了两行数据,sessiona的select语句对ftime这两个记录之间的间隙加了锁,间隙和加锁状态如图:
也就是说,2017-4-1和2018-4-1这两个记录之间的间隙会被锁住,那么sessionb的两条插入语句都应该进入锁等待状态。但是从效果上看,第一个insert语句是可以执行成功的,因为对于引擎来说,p2018和p2019是不同的表,2017的下一个记录不是2018-4-1而是p2018中的supremum,所以在t1时刻索引如图:
由于分区表的规则,sessiona只操作了p2018,sessionb要插入2018-2-1是可以的但要写入2017-12-1要等待sessiona的间隙锁.
对于myisam引擎:
因为在sessiona中,sleep了100秒,由于myisam只支持表锁,所以这条update会锁住整个表t的读,但是结果是,b的第一条语句是可以执行的,第二条语句才进入锁等待状态.
这是myisam表锁只在引擎层实现的,sessiona加的表锁,是所在p2018上,因此只会堵住分区上执行的查询,落到其他分区的查询不受影响。这样看来,分区表还不错,为什么不用呢,我们使用分区表的一个原因就是单表过大,那么不使用分区表,就要使用手动分表的方式.
手动分表需要创建t_2017,t_2018,t_2019,也就是找到需要更新的所有分表,依次执行,这和分区表无实质的差别,两者一个由serverceng决定使用哪个分区,一个由应用层代码决定使用哪个分表,因此,从引擎层看无实际差别。其实主要区别是在server层:打开表行为.
分区策略 。
每当第一次访问一个分区表时,mysql需要把所有分区都访问一遍:如果分区很多,比如查过了1000个,mysql启动的时候,open_files_limit默认为1024,那么就会在访问表的时候,由于打开了所有文件,超过了上限而报错.
mysiam使用的分区策略成为通用分区策略,每次访问分区都是有server层控制。有比较严重的性能问题.
innodb引擎引入了本地分区策略,是在innodb内部自己管理打开分区的行为.
分区表的server层行为 。
从server层看,一个分区表就是一个表.
虽然b只操作2017分区,但是由于a持有整个表t的mdl锁,导致了b的alter语句被堵住。如果是使用普通分表,不会跟另外一个分表上的查询语句出现mdl冲突.
小结:
分区表应用场景 。
分区表的优势是对业务透明,相对于用户分表来说,使用分区表的业务代码更简洁,分区表可以很方便的清理历史数据.
alter table t drop partition 操作是删除分区文件,效果跟drop类似,与delete相比,优势是速度快,对系统影响小.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://www.cnblogs.com/jimmyhe/p/11241929.html 。
最后此篇关于Mysql临时表及分区表区别详解的文章就讲到这里了,如果你想了解更多关于Mysql临时表及分区表区别详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
平时很少在jquery中用到this。查看代码时发现用到了,就调试出this的值,心想原来如此。还是挺有用的。这里总结一下this与$(this)的区别和使用。 $(this)生成的是什么?
使用单例类和应用程序范围的托管 bean 来保存应用程序数据有区别吗? 我需要查找某些 JNDI 资源,例如远程 bean 接口(interface),因此我为自己编写了一个单例来缓存我的引用并且只允
如果您仔细查看包含的图片,您会注意到您可以使用 Eclipse IDE 重构 Groovy 代码并将方法转换为闭包,反之亦然。那么,闭包到底是什么,它与方法有什么不同呢?有人可以举一个使用闭包的好例子
vagrant box repackage有什么区别( docs ) 和 vagrant package ( docs )? 我意识到 vagrant package仅适用于 VirtualBox 提
我想看看是否有人可以解释为什么以下代码适用于 valueOf 但不适用于其他代码。 import java.math.BigDecimal; public class Change { publ
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicates: What is Closures/Lambda in PHP or Javascript in layman te
This question already has answers here: Vagrant, Docker, Puppet, Chef (3个答案) 2年前关闭。 docker和chef有什么共同
以下代码在95%的机器上产生相同的输出,但是在几台机器上却有所不同。在 Debug模式下,输出: Changing from New to Fin OK 但在 Release模式下: Changing
////Creating Object var Obj; // init Object Obj= {}; 它们之间有什么区别两个? 有没有可能把它变成一个单行? 这样使用有什么好处吗?
我想找出定时器服务之间的区别。我应该使用哪个以及何时使用。我正在使用 Jboss 应用服务器。 1) java.ejb.Schedule。 @Schedule注解或配置自xml。 2) javax.e
我发现在 C++ 中可以通过三种不同的方式将对象传递给函数。假设我的类(class)是这样的: class Test { int i; public: Test(int x);
有什么区别。 public class Test { public static void main(String args[]) { String toBeCast = "c
如果我有一列,设置为主索引,设置为INT。 如果我不将其设置为自动递增,而只是将唯一的随机整数插入其中,与自动递增相比,这是否会减慢 future 的查询速度? 如果我在主索引和唯一索引为 INT 的
这两种日期格式有什么区别。第一个给出实际时间,第二个给出时间购买添加时区偏移值。 NSDateFormatter * dateFormatter = [[NSDateFormatter alloc]
如果有一个函数,请说foo: function foo() { console.log('bar'); } 那么在 JavaScript 中,从另一个函数调用一个函数有什么区别,如下所示: f
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 4 年前。 Improv
代码是什么: class Time { private: int hours; int minutes; int seconds; pu
我知道这是非常基本的,但有人介意解释一下这两个数组声明之间的区别吗: #include array myints; ...和: int myints[5]; ...以及为什么 myints.size
我学会了如何根据 http://reference.sitepoint.com/css/specificity 计算 css 特异性但是,基于this reference,我不明白伪类(来自c)和伪元
为什么在运行 2) 时会出现额外的空行?对我来说 1 就像 2。那么为什么 2) 中的额外行? 1) export p1=$(cd $(dirname $0) && pwd) #
我是一名优秀的程序员,十分优秀!