Mysql分区表 介绍和使用

试想这样一个场景:

你有一张表,存储引擎为InnoDB,里面存储的数据量达到了上亿级别。
此时,因为数据量巨大,肯定不能在每次查询的时候都扫描全表。
就算是使用索引(B-Tree),除非使用索引覆盖查询,否则数据库服务器需要根据查询的结果回表,查询所有符合条件的数据,
如果数据量巨大,会产生大量的随机IO,最终使得应用程序僵死。另外,这种数据量下,索引维护的代价也非常高。

分区表适用的场景?

分区表适用于数据量非常大,并且拥有某个特定字段可以据此将数据划分成几块的场景。
例如用户购买的商品记录表,可以依据购买时间,将全量记录划分为多个子分区。

那么有同学会问,为什么不直接用物理分表呢?

例如,有一张存储了3亿条商品数据的表goods,出于性能考虑,我们可能会将表拆分成300个子表,每张表存储100W条数据,
此时,我们有了goods_0、goods_1....goods_299。
但这样做的问题是:开发者需要自行按照特殊条件,对于自身要操作的表做判断,然后自行改写sql去操作指定的物理子表,
这样的问题在于,将开发逻辑变得复杂化,并且代码变得"丑"了。
如果你使用了某些ORM框架,那么就更烦人了,你需要改写model定位自身table的逻辑。

Redis ZipMap 数据结构和源码剖析

在redis中,使用 hashtable 实现了 set、sorted set、hash 结构。而单纯的 hashtable ,因为是一次分配一大块内存,所以在存储少量数据时会存在空间利用率很低的问题。

redis 是内存数据库,而内存是昂贵的,所以需要尽量避免内存的浪费,所以有了 zipmap 结构。

zipmap?

我们通过 what、why、how 来对 zipmap 进行全面的认识

what?(它是什么)

ZipMap 实质上就是一个特殊格式的字符串。

why?(为什么要用它)

因为redis是个内存数据库,要尽量避免内存浪费

how?(它是怎么实现的)

zipmap 是用连续内存保存 key-value 对的结构,查询时是依次遍列每个 key-value 对,直到查到为止。其存储结构如下所示:
zipmap 结构图示

多进程+协程 (multiprocessing + gevent)

前面讲了为什么Python里推荐用多进程而不是多线程,但是多进程也有其自己的限制:相比线程更加笨重、切换耗时更长,并且在python的多进程下,进程数量不推荐超过CPU核心数(一个进程只有一个GIL,所以一个进程只能跑满一个CPU),因为一个进程占用一个CPU时能充分利用机器的性能,但是进程多了就会出现频繁的进程切换,反而得不偿失。

不过特殊情况(特指IO密集型任务)下,多线程是比多进程好用的。

举个例子:给你200W条url,需要你把每个url对应的页面抓取保存起来,这种时候,单单使用多进程,效果肯定是很差的。为什么呢?

例如每次请求的等待时间是2秒,那么如下(忽略cpu计算时间):

1、单进程+单线程:需要2秒*200W=400W秒==1111.11个小时==46.3天,这个速度明显是不能接受的

2、单进程+多线程:例如我们在这个进程中开了10个线程,比1中能够提升10倍速度,也就是约4.63天能够完成200W条抓取。
请注意,这里的实际执行是:线程1遇见了阻塞,CPU切换到线程2去执行,遇见阻塞又切换到线程3等等,
10个线程都阻塞后,这个进程就阻塞了,而直到某个线程阻塞完成后,这个进程才能继续执行,
所以速度上提升大约能到10倍(这里忽略了线程切换带来的开销,实际上的提升应该是不能达到10倍的),
但是需要考虑的是线程的切换也是有开销的,所以不能无限的启动多线程(开200W个线程肯定是不靠谱的)

3、多进程+多线程:这里就厉害了,一般来说很多人就是使用这个方法,多进程下,每个进程都能占一个cpu,
而多线程从一定程度上绕过了阻塞的等待,所以比单进程下的多线程又更好使了,例如我们开10个进程,
每个进程里开20W个线程,执行的速度理论上是比单进程开200W个线程快10倍以上的(为什么是10倍以上而不是10倍,
主要是cpu切换200W个线程的消耗肯定比切换20W个进程大,考虑到这部分开销,所以是10倍以上)。

还有更好的方法吗?答案是肯定的,它就是:

Nginx - Location 匹配规则

语法规则

location = /uri        = 表示精确匹配某个uri
location ^~ /uri       ^~ 表示精确的前缀匹配以uri开头的请求,优先级在正则之前
location ~ uri         ~ 表示区分大小写的正则匹配,这里的uri就是一个正则表达式
location ~* uri        ~* 表示不区分大小写的正则匹配,这里的uri就是一个正则表达式
location /uri          不带修饰符,表示精确的前缀匹配以uri开头的请求,优先级在正则之后
location /             通用匹配,未匹配到其他location的请求都会走到这里。 
                       其实就相当于匹配以/开头的请求,自然就能匹配全部

匹配顺序优先级

当存在多个同级location时,表达式越精确,优先级越高

例如:匹配http://localhost/wapabcd 时,/wap 优先级高于/wa

当存在多个不同级location时,匹配的优先级如下:

1、 =(完全精确匹配)
2、 ^~(带修饰符的前缀精确匹配)
3、 ~(区分大小写的正则匹配)
4、 ~*(不区分大小写的正则匹配)
5、 /uri(无修饰符的前缀精确匹配)
6、 /(通用匹配)

例子:

Linux命令之 chmod(改变文件存取模式)

命令格式

chmod [options] mode files

只有文件属主或特权用户才能使用该功能来改变文件存取模式。mode可以是数字形式或以who opcode permission形式表示。who是可选的,默认是a(所有用户)。只能选择一个opcode(操作码)。可指定多个mode,以逗号分开。

options:

-c,--changes
只输出被改变文件的信息
-f,--silent,--quiet
当chmod不能改变文件模式时,不通知文件的用户
--help
输出帮助信息。
-R,--recursive
可递归遍历子目录,把修改应到目录下所有文件和子目录
--reference=filename
参照filename的权限来设置权限
-v,--verbose
无论修改是否成功,输出每个文件的信息
--version
输出版本信息。