来源:http://www.day32.com/MySQL/ MySQL初级性能调整脚本 该脚本从“SHOW STATUS LIKE…”和“SHOW VARIABLES LIKE…”中提取信息来给出调整服务器变量的合理建议。他可以兼容所有MySQL 3.23以及更高版本(包括5.1)。 目前它会对以下内容做出建议: Slow Query Log Max Connections Worker Threads Key Buffer Query Cache Sort Buffer Joins Temp Tables Table (Open & Definition) Cache Table Locking Table Scans (read_buffer) Innodb Status MySQL复制从服务器延迟跟踪器 检查MySQL复制从服务器状态 MYSQL_BACKUP.sh 更多内容请看原页面:http://www.day32.com/MySQL/
声明:此对比仅限于本人对公司的服务器情况所做的比较,并非通用和全面的比较。 随着公司业务的进一步扩展,服务器所承受的用户也越来越多,我也琢磨着怎么进一步提高数据库服务器的负载能力。我查到一些资料,InnoDB支持事务,支持行级锁,而且比MyISAM更具有伸缩性,MyISAM对于读取多写入少的数据库更好。 公司只有一台数据库服务器,是租用的万网双线机房的服务器(独享II型),配置并不好: CPU:PD2.8G(双核) 内存:1G DDRII 硬盘:SATA -80G 网卡:双1000M 安装的CentOS 3.2——万网没有别的Linux操作系统,可能都是预先安装好,拿来就可以用。 我安装了MySQL 5.0,用的是从MySQL网站上下载的RPM包。 公司的数据库的操作中,更新和插入占了大部分,而一般的网页型的网站则大部分仅仅是查询,很多还可以被缓存,将公司的数据库查询的记录和我的BLOG的数据库查询的记录做个对比: (注:公司的服务器上使用了memcached,应用层将大部分记录缓存于此减轻数据库压力,所以在图上看不到多少Cache hit) 这样,我武断地认为,因为公司的数据库主要是插入和更新这些操作,所以应该采用InnoDB格式才能更好地发挥效果。而事与愿违,在转换了格式之后,性能却出现了大幅度下滑,在每天的定时数据统计期间,还可能会导致数据库大量连接阻塞,查看了性能图像之后,发现是CPU大量的时间都用于I/O等待上了: 对应的IO状态的性能图志: 大家可以从图看上到,使用了InnoDB的几天在图中间反应为大量的磁盘写操作,于是之后我又切换回MyISAM,可见MyISAM的写操作少得多。 为什么会导致这种情况发生呢? 可能和InnoDB的性质有关。InnoDB是ACID的,这种ACID的数据库都对磁盘的IO性能要求很高,也要求更大的内存。很多数据库服务器往往都使用SCSI RAID,动辄4G、8G甚至16G内存——由于我对数据库的研究并不是很深,我隐约记得InnoDB有个会导致性能下降的双重写入问题,以及log的flush问题(向达人求证)。而公司租用的这台服务器,内存小,硬盘也只是SATA的,瓶颈是十分明显的。 当然,据很多测试表明,在高配的情况下,InnoDB有更大的优势——就好比谁会在这种机器上装Oracle呢?即使Oracle在这种机器上表现差,又有谁会质疑Oracle的强大呢? 所以我的结论是,如果数据库的硬件配置低,而应用又对事务等高级特性要求不是很高的话,可以依然采用MyISAM。
作者:Sanjay Ghemawat, Paul Menage 原文 翻译:ShiningRay 动机 TCMalloc要比glibc 2.3的malloc(可以从一个叫作ptmalloc2的独立库获得)和其他我测试过的malloc都快。ptmalloc在一台2.8GHz的P4机器上(对于小对象)执行一次malloc及free大约需要300纳秒。而TCMalloc的版本同样的操作大约只需要50纳秒。malloc版本的速度是至关重要的,因为如果malloc不够快,应用程序的作者就很有可能在malloc之上写一个自己的自由列表。这就可能导致额外的代码复杂度,以及更多的内存占用――除非作者本身非常仔细地划分自由列表的大小并经常从自由列表中清除空闲的对象。 TCMalloc也减少了多线程程序中的锁争用情况。对于小对象,几乎已经达到了零争用。对于大对象,TCMalloc尝试使用粒度较好和有效的自旋锁。ptmalloc同样是通过使用每线程各自的场地来减少锁争用,但是ptmalloc2使用每线程场地有一个很大的问题。在ptmalloc2中,内存可能会从一个场地移动到另一个。这有可能导致大量空间被浪费。例如,在一个Google的应用中,第一阶段可能会为其URL标准化的数据结构分配大约300MB内存。当第一阶段结束后,第二阶段将从同样的地址空间开始。如果第二个阶段被安排到了一个与第一阶段什?用的场地不同的场地,这个阶段不会复用任何第一阶段留下的的内存,并会给地址空间添加另外一个300MB。类似的内存爆炸问题也可以在其他的应用中看到。 TCMalloc的另一个好处是小对象的空间最优表现形式。例如,分配N个8字节对象可能要使用大约8N * 1.01字节的空间。即,多用百分之一的空间。而ptmalloc2中每个对象都使用了一个四字节的头,(我认为)并将最终的尺寸规整为8字节的倍数,最后使用了16N字节。 使用 要使用TCMalloc,只要将tcmalloc通过“-ltcmalloc”链接器标志接入你的应用即可。 你也可以通过使用LD_PRELOAD在不是你自己编译的应用中使用tcmalloc: $ LD_PRELOAD=”/usr/lib/libtcmalloc.so” LD_PRELOAD比较讨巧,我们也不十分推荐这种用法。 TCMalloc还包含了一个堆检查器以及一个堆测量器。 如果你更想链接不包含堆测量器和检查器的TCMalloc版本(比如可能为了减少静态二进制文件的大小),你可以接入libtcmalloc_minimal。 概览 TCMalloc给每个线程分配了一个线程局部缓存。小分配可以直接由线程局部缓存来满足。需要的话,会将对象从中央数据结构移动到线程局部缓存中,同时定期的垃圾收集将用于把内存从线程局部缓存迁移回中央数据结构中。 TCMalloc将尺寸小于<= 32K的对象(“小”对象)和大对象区分开来。大对象直接使用页级分配器(一个页是一个4K的对齐内存区域)从中央堆直接分配。即,一个大对象总是页对齐的并占据了整数个数的页。 连续的一些页面可以被分割为一系列小对象,而他们的大小都相同。例如,一个连续的页面(4K)可以被划分为32个128字节的对象。 小对象的分配 每个小对象的大小都会被映射到170个可分配的尺寸类别中的一个。例如,在分配961到1024字节时,都会归整为1024字节。尺寸类别这样隔开:较小的尺寸相差8字节,较大的尺寸相差16字节,再大一点的尺寸差32字节,如此类推。最大的间隔(对于尺寸 >= ~2K的)是256字节。 一个线程缓存对每个尺寸类都包含了一个自由对象的单向链表。 当分配一个小对象时: 我们将其大小映射到对应的尺寸类中。 查找当前线程的线程缓存中相应的自由列表。 如果自由列表不空,那么从移除列表的第一个对象并返回它。当按照这个快速通道时,TCMalloc不会获取任何锁。这就可以极大提高分配的速度,因为锁/解锁操作在一个2.8GHz Xeon上大约需要100纳秒的时间。 如果自由列表为空: 从该尺寸类别的中央自由列表(中央自由列表是被所有线程共享的)取得一连串对象。 将他们放入线程局部的自由列表。 将新获取的对象中的一个返回给应用程序。 如果中央自由列表也为空:(1) 我们从中央页分配器分配了一连串页面。(2) 将他们分割成该尺寸类的一系列对象。(4) 像前面一样,将部分对象移入线程局部的自由列表中。 大对象的分配 一个大对象的尺寸(> 32K)会被除以一个页面尺寸(4K)并取整(大于结果的最小整数),同时是由中央页面堆来处理的。中央页面堆又是一个自由列表的阵列。对于i < 256而言,第k个条目是一个由k个页面组成的自由列表。第256个条目则是一个包含了长度>= 256个页面的自由列表: k个页面的一次分配通过在第k个自由列表中查找来完成。如果该自由列表为空,那么我们则在下一个自由列表中查找,如此继续。最终,如果必要的话,我们将在最后一个自由列表中查找。如果这个动作也失败了,我们将向系统获取内存(使用sbrk、mmap或者通过在/dev/mem中进行映射)。 如果k个页面的一次分配行为由连续的长度> k的页面满足了,剩下的连续页面将被重新插回到页面堆的对应的自由列表中。 跨度(Span) TCMalloc管理的堆由一系列页面组成。连续的页面由一个“跨度”(Span)对象来表示。一个跨度可以是已被分配或者是自由的。如果是自由的,跨度则会是一个页面堆链表中的一个条目。如果已被分配,它会是一个已经被传递给应用程序的大对象,或者是一个已经被分割成一系列小对象的一个页面。如果是被分割成小对象的,对象的尺寸类别会被记录在跨度中。 [...]
作者:ShiningRay @ Nirvana Studio 随着网络的发展,网速和机器速度的提高,越来越多的网站用到了丰富客户端技术。而现在Ajax则是最为流行的一种方式。JavaScript是一种解释型语言,所以能无法达到和C/Java之类的水平,限制了它能在客户端所做的事情,为了能改进他的性能,我想基于我以前给JavaScript做过的很多测试来谈谈自己的经验,希望能帮助大家改进自己的JavaScript脚本性能。 语言层次方面 循环 循环是很常用的一个控制结构,大部分东西要依靠它来完成,在JavaScript中,我们可以使用for(;;),while(),for(in)三种循环,事实上,这三种循环中for(in)的效率极差,因为他需要查询散列键,只要可以就应该尽量少用。for(;;)和while循环的性能应该说基本(平时使用时)等价。 而事实上,如何使用这两个循环,则有很大讲究。我在测试中有些很有意思的情况,见附录。最后得出的结论是: 如果是循环变量递增或递减,不要单独对循环变量赋值,应该在它最后一次读取的时候使用嵌套的++或–操作符。 如果要与数组的长度作比较,应该事先把数组的length属性放入一个局部变量中,减少查询次数。 举例,假设arr是一个数组,最佳的遍历元素方式为: for(var i=0, len = arr.length;i<len;i++){…} 或者,如果无所谓顺序的话: for(var i=arr.length;i>0;i–){…} 局部变量和全局变量 局部变量的速度要比全局变量的访问速度更快,因为全局变量其实是全局对象的成员,而局部变量是放在函数的栈当中的。 不使用Eval 使用eval相当于在运行时再次调用解释引擎对内容进行运行,需要消耗大量时间。这时候使用JavaScript所支持的闭包可以实现函数模版(关于闭包的内容请参考函数式编程的有关内容) 减少对象查找 因为JavaScript的解释性,所以a.b.c.d.e,需要进行至少4次查询操作,先检查a再检查a中的b,再检查b中的c,如此往下。所以如果这样的表达式重复出现,只要可能,应该尽量少出现这样的表达式,可以利用局部变量,把它放入一个临时的地方进行查询。 这一点可以和循环结合起来,因为我们常常要根据字符串、数组的长度进行循环,而通常这个长度是不变的,比如每次查询a.length,就要额外进行一个操作,而预先把var len=a.length,则就少了一次查询。 字符串连接 如果是追加字符串,最好使用s+=anotherStr操作,而不是要使用s=s+anotherStr。 如果要连接多个字符串,应该少使用+=,如 s+=a;s+=b;s+=c; 应该写成 s+=a + b + c; 而如果是收集字符串,比如多次对同一个字符串进行+=操作的话,最好使用一个缓存。怎么用呢?使用JavaScript数组来收集,最后使用join方法连接起来,如下 var buf = new Array();for(var i = 0; i < 100; i++){ buf.push(i.toString());}var all = buf.join(""); [...]