Skip to content

{ Author Archives }

Chapter 7 操作系统和硬件优化

MySQL 服务器中最弱的部分决定了其性能,它的操作系统和硬件通常也会成为限制因素。磁盘大小、可用内存、CPU 资源、网络和连接它们的组件一起决定了系统的最终容量。
前面的章节主要讨论了 MySQL 服务器和应用程序,这种类型的调优是很关键的,但是同时也应该考虑到硬件并且适当地配置系统。例如,如果工作负载是 I/O 密集型的,那么设计应用程序的一个目的就是最小化 MySQL 的 I/O 负载。但是在通常情况下,升级 I/O 子系统,安装更多内存或重新配置已有磁盘是更为明智的选择。

7.1 什么限制了 MySQL 的性能

许多不同的硬件可以影响 MySQL 的性能,但是最常见的两个瓶颈是 CPU 饱和与 I/O 饱和。CPU 饱和发生在 MySQL 使用的数据能被装入内存,或者能够尽快根据需要从磁盘上读取的时候。密集的加密操作及在多个产品之间执行无索引的联接操作都是引发 CPU 饱和的例子。

从另一方面来说,I/O 饱和通常发生在需要的数据比内存多得多的时候。如果应用程序分布在网络上,查询数据相当巨大,或者要求很低的延时,瓶颈就会转移到网络上。

发现瓶颈通常不是显而易见的事情。某个区域的弱点通常会给其它的子系统带来压力,问题通常就会表现在其它子系统上面。例如,假设没有足够的内存,MySQL 就会刷新(Flush)缓存,为需要的数据腾出空间,然后再马上把数据重新读回来(读写操作都会这样),因此内存不足就表现为 I/O 容量不够。同样地,达到饱和的内存问题会表现为 CPU 问题。事实上,在说应用程序有『CPU 瓶颈』或『CPU 密集』的时候,通常是指瓶颈出在计算上。稍后再解释这个问题。

7.2 如何为 MySQL 选择 CPU

在升级当前硬件或购买新硬件的时候,应该考虑工作负载不是 CPU 密集的。
可以通过检查 CPU 使用率来确认负载是否是 CPU 密集的,但要注意不是只检查 CPU 总体负载有多重,而是要查明对于最重要的查询,CPU 使用率和 I/O 之间的平衡,以及注意 CPU 的负载是否均衡。可使用 mpstat、iostat 及 mstat(例子在本章最后)这些工作来查明什么因素限制了服务器的性能。

7.2.1 快 CPU 好还是多 CPU 好?

对于 CPU 密集的负载,MySQL 通常从更快的 CPU 中获益(不是更多 CPU),但事实并不总是如此,因为这依赖于负载和 CPU 的数量。但是,当前 MySQL 的架构对多 CPU 的扩展性不好,并且 MySQL 不能在多个 CPU 上并行地运行某个查询,因此在对于单个 CPU 进行密集的查询时,CPU 速度限制了响应速度。通常来说,想要的性能有两类:

低延迟(快速响应时间)

为实现这个目标,需要快速的 CPU,因为单个查询只能使用一个 CPU。

高吞吐量

如果可以同时运行很多查询,那么就可能会从多 CPU 中得益。但是,这是否能凑效还取决于许多因素。因为 MySQL 在多个 CPU 上的扩展性很差,所以通常使用更快的 CPU 更好。

如果使用了多个CPU,并且没有并发地运行查询。MySQL 的后台线程可以为一些任务分配额外的 CPU 资源。这些任务包括清理 InnoDB 缓冲区、网络操作等。但是,这些工作比起查询来通常不算什么。如果使用双 CPU 系统来运行一个 CPU 密集的查询,那么某个 CPU 可能在 90% 的时间都是空闲的。

快速的 CPU, 而不是多个 CPU,会让 MySQL复制(下一章)达到最佳工作状态。如果工作负载是 CPU 密集型的,主服务器上的并行负载能轻易地变成从服务器无法跟上单一负载,即使从服务器比主服务器更强大也不能避免这种情况,这说明 I/O 子系统,而不是 CPU,常常会成为从服务器的瓶颈。

如果工作负载是 CPU 密集型的,决定到底是采用快速的 CPU 还是多 CPU 的方式就需要明白查询到底做了什么。在硬件层,查询可能处于执行状态或等待状态。最常见的等待原因有几种:查询在运行队列中(进程可以运行,但是 CPU 繁忙)、等待锁定,以及等待磁盘或网络。在这些情况下,通常需要更快的 CPU。(但是也有例外,例如查询正在等待 InnoDB 日志缓存互斥量,它只有在I/O 完成之后被释放掉,这意味着实际需要更多的 I/O 容量。)

MySQL 在某些负载下能够使用多个 CPU。例如,假设有许多连接正在查询不同的表(因此不会竞争表锁,但对于 MyISAM 表和 Memory 表,这会成为问题),并且服务器的总吞吐量比单个查询响应要重要得多,吞吐量在这种场景下会很高,因为所有的线程可以并发地运行并且彼此不会有竞争。要再次说明的是,这在理论上比实际上工作得更好:不管查询读取的是否是相同的表,InnoDB 都有扩展性问题,并且 MyISAM 在每个键缓冲区上有全局锁。MyISAM 表上的全表扫描是可以并发地运行而不会引发竞争的一个例子。

MySQL 宣称正处于设计中的 Falcon 存储引擎可以使用至少 8 个CPU , 所以未来的 MySQL 也许能比现在更有效地使用多 CPU。但是只有时间能证明 Falcon 的真实扩展性。

7.2.2 CPU 架构

现在 64 位架构比几年前更加流行。MySQL 在 64 位架构上工作得很好,尽管有某些内部机制不能与 64 位系统兼容。例如,在 MySQL 5.0 中,每个 MyISAM 键缓冲区都被限制在 4GB,这是由 32 位整数寻址的地址空间所决定的(但是可以通过定义多个键缓冲区来绕过这个问题)。

为所有的新硬件选择 64 位架构是一个好主意。如果没有使用 64 位操作系统和 64 位 CPU,就不能有效地使用大量的内存。尽管一些 32 位系统能够支持大量的内存,但是系统不能像 64 位系统那样有效地使用它们,并且 MySQL 也不能很好地使用它们。



  1. Look beyond the obvious when you think you’ve found a bottleneck. A weakness in one area often puts pressure on another subsystem, which appears to be the problem. For example, if you don’t have enough memory, MySQL might have to flush caches to make room for data it needs – and then, an instant later, read back the data is just flushed(this is true for both read and write operations). The memory scarcity can thus appear to be a lack of I/O capacity. Similarly, a saturated memory bus can appear to be a CPU problem. In fact, when we say that an application has a “CPU bottleneck” or is “CPU-bound”, what we really mean is that there is a computational bottleneck. We delve into this issue next.Back

Charpter 1 文本

字符串基础

 big = "This is a long string \n\
 that prints on two lines."

bigger = """
This is an even
bigger string that
spans three lines.
"""

使用三引用符,无须在文本中加入续行符和换行符,因为文本将按照原貌被存储在 Python 的字符串对象中。也可以在字符串前面加一个 r 或者 R,表示该字符串是一个真正的『原』字符串,需要它的原貌:

big = r"This is a long string \
with a backslash and a newline in it"

使用『原』字符串,反斜线转义被完全忽略了。还可以在字符串前面加一个 u 或者U来使之成为一个 Unicode 字符串:

hello = u'Hello\u0020World'

字符串是无法改变的,那意味着无论对它进行什么操作,总是创建了一个新的字符串对象,而不是改变了原有的字符串对象。字符串是字符的序列,所以也可以通过索引的方法访问单个字符。

mystr = "my string"
mystr[0]      #  'm'
mystr[-2]     #  'n'

也可以用切片的方法访问字符串的一个部分:

mystr[1:4]    #  'y s'
mystr[3:]     #  'string'
mystr[-3:]    #  'ing'
mystr[:3:-1]  #  'gnirt'
mystr[1::2]   #  'ysrn'

可以通过循环遍历整个字符串:

for c in mystr:

上述方法将 c 依次绑定到了 mystr 中的每一个字符。还可以构建另一个序列:

list(mystr)    #返回  ['m', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g']

通过简单的加法,可以实现字符串的拼接:

mystr + 'oid'  #  'my stringoid'

乘法则完成对字符串多次重复:

'xo' * 3       #  'xoxoxo'

总之,可以对字符串做任何能够对其它系列作的操作,前提是不能试图改变字符串序列,因为字符串是不能改变的。
mystr.isdigit( ) 测试字符串的内容,如果 mystr 不是空的且所有字符都是数字,则返回 True,否则 False。
mystr.count('str') 在 mystr 字符串中搜索 str 字符串出现的次数。

mystr.isdigit()         #  False
mystr.uppper()          #  'MY STRING'
mystr.count('str')      #  1

如果有一个庞大的包含多行文本的字符串,可以用 splitlines 来将其分割为多个单行字符串并置入一个列表中:

list_of_lines = one_large_string.splitlines()

然后还可以用 join 来重新生成一个庞大的单个字符串:

one_large_string = '\n'.join(list_of_lines)

每次处理一个字符

任务
用每次处理一个字符的方式来处理字符串。
解决方案
可以创建一个列表,列表的

thestring = 'the string'
thelist = list(thestring)
print(thelist)

for c in thestring:
  print(c)

[print(c) for c in thestring]

字符和字符值之间的转换

任务
将一个字符转化为相应的 ASCII(ISO) 或者 Unicdoe 码,或者反其道而行之。
解决方案

注释

  • 切片操作符中的第一个数(冒号之前)表示切片开始的位置,第二个数(冒号之后)表示切片到哪里结束。如果不指定第一个数,Python 就从序列首开始。如果没有指定第二个数,则 Python 会停止在序列尾。注意,返回的序列从开始位置 开始 ,刚好在 结束 位置之前结束。即开始位置是包含在序列切片中的,而结束位置被排斥在切片外。>
    s[start:stop] start 和 stop 均可忽略。start 从某一位置开始,包含该位置,stop 到某一位置结束,不包含该位置。
    如果 start 和 end 为负数,及从结尾的第一个字符开始(右边第一个字符)。正数从开始的第一个字符开始(左边第一个字符)。
    s[start:stop:step]start、stop 和 ste p均和忽略,step 是切片时的步长,默认是一个接一个,如果为负数,即从字符串右边开始取值。Back
Tagged ,

淘宝技术嘉年华 – iDataForum

7 月 10 日 idataforum

吸取了昨天的教训,早上不急不慢的把早餐吃好后才晃悠过去。到达会场时,时间还尚早。看了下周围的同学,大多都是低头,或是相邻的在窃窃私语着。

 

依照惯例,上午还是主论坛

 

下午有三个分论坛
分论坛一 —— MySQL

分论坛二 —— NoSQL

分论坛三

 

本来,也打算对参加的每场做下备注,但写完周晓方老师的那场后,脑子里空白的很。拼命搜索记忆,结果也为零。后面就干脆把已写下来的全部删除,做个引导的目录就算了吧。

或许,我是真的在患失忆症,也许也因为其他的一些原因,影响了整个的记忆。

淘宝技术嘉年华 – TCon

幸好,我所在的组没有其他人报名参加这次 2011 淘宝技术嘉年华 的活动,否则,从经济的角度来说,以我女生尴尬的身份,估计是很难被批准的。

这次的技术嘉年华,把之前单独举行已在业界较出名的 D2, idataforum 集合到一块儿,再加上还有后面推出的不需报名的 淘宝技术专场,Node 沙龙,圆桌会议 ……等等可以说在那两天会前会后,莫干山路上见到的来来往往的行人,都是来参加这次会议的。之下就大概记录下参加的两天的会议行程。

7 月 9 日 TCon 分会场

之前,有看到公告说是 8 点开始签到, 因为一些耽搁,等我 8:45 匆匆忙忙到达会场的时候,见里面寥寥几人, 都在低头翻着签到时所发的资料。 这有点让我惊讶,不致这么少吧。后面,陆陆续续的人进来,终至满场后旁边还零零散散的站着好些。原来,是大家到得较晚而已。(会后,从围脖上得知,里面还是有些打酱油的,因为隔壁 淘宝技术专场爆场,好多后面赶过去的同学无法挤入会场,不得不转战我们这边)。

 

上午是主会场,9:45 时才开始,先淘宝网的 张建锋/行癫 致辞,很简短, 但有提出测试中的一些问题,如:测试行业平台化和自动化的挑战;测试人员安排;测试与开发流程的关系;保证研发效率和产品质量是测试的目的等。

 

之后,是淘宝的 夏林娜/郭芙 做介绍,主题是《 Testing Business in Taobao》 。她提出测试有 『器』,『术』,『道』 (其实,我很期望她能对这三个做些具体的解析)。之后,用一登录的界面做示例,为了增加与听众的互动,于是提问,『谁能说说这一登录界面需要做哪些方面的测试?』。但效果甚微,因为回答的同学有些紧张,只说需要做 UI 方面,然后 SQL 注入等等的测试。这样一来,加上 她本身好像也有点紧张?,话题一下扩散,等再回来,总感觉不在状态。
slides 很少,但其中 这一张图(图 1),让我印象深刻,因为之前我并不是测试人员,甚至,连边都挨不上。而这张图,让我对所需要做的测试内容,有了一大概的轮廓。


图1

部分提问整理:
Q: 淘宝安全方面是怎样测试的?
A: 基本的安全方面的测试,有一扫描工具 STC (Security Test Center)。
Q: 做白盒?
A: 白盒测试。
Q 在代码更新时,这个工具什么时候开始检测, 是 STC 也管理代码?
A: 是手工将更新的代码的 SVN 地址 提交到 STC, STC 再开始检测。

Q:怎样展开测试,或者是做好测试?(问题记不太清了,看笔记,意思大概是这样)
A:最主要是要对产品有整体的了解。然后,做测试要做到 5W1H。5W是, Why, 为什么要做这个测试; What,要做那些方面的测试; Who,由谁去做测试; When,什么时候做测试,一般由当时场景,开发人员定义;1H 是 How, 即怎样做测试,根据需求准备好测试用例,再执行。(数数,是不是少了个 『W』,拉下的那个是 Which,根据测试用例的重要性,哪个先做,或者 Where ,哪个地方重要些,先测?我自圆其说的解释好像都说得通。也许,在她的答案中,这两个 W 都不是她的 W)。

Q:对于测试的结果要怎样评估?
A:折中,主要是在产品开发前期, PM ,QA 等沟通好,定下一产品上线的标准。

Q: 在采用敏捷开发模式的方式下,测试怎样分工,然后对于研发工具,流程建设方面能否给些建议?
A:测试人员对于业务和技术都要想当程度上的了解, 然后, 敏捷项目的管理理念 scrum,就注重 Team 的建设。(这个回答记录的不是很清楚,但我想,这里是否给出的是:测试人员除了需要对于业务和技术方面的了解,更多还要有团队的精神)。

会后感想:这场好像演讲者准备得并不是很充分,有点敷衍的感觉。

 

Google 日本 的 Matt Devore 做的 《NativeDriver–Testing tool for multiple platforms》 是上午主会场 的最后一场。
忍不住先八卦下,Matt 上台后,大家都有点兴奋,尤其我自己,见到外国友人,现已是很稀松平常的事,但要见到 Google 的开发人员,可不是件容易的事,更何况,我还是 Google 的 粉丝。『大家好』,这是 Matt 说的第一句话,是中文。所有人听到后都情不自禁的鼓起了掌,还伴随着很 Happy 的笑声。最主要是心里头一块石头落地,不用听英文的演讲啊~~~可惜,这话过后,没高兴几秒钟,Matt 在继续用中文自我介绍完后,接着就说道:『我的中文还不是很好,所以这里还是用英文演讲…』,顿时,会场空中飘过一阵唉声。

八卦完,回到正题。这个议题主要是 Matt 介绍他负责开发的 NativeDriver,该工具是使用原生 UI 而不是浏览器 UI 的自动化测试框架,它主要用于 Android 应用程序的功能测试。目前已有 Andriod, iOS, Windows 版本。

会后感想:这场演讲下来,气氛变得有点沉闷,Matt 也好像是比较严肃之人,除开始那一句中文逗笑大家后, 之后,整个会场就都只有他的讲话声。然后,因为期间也没有同声翻译,或者做下解说,能听懂英文的还好,听不懂的,就我周围,好几个人都已昏昏入睡。好在结束时有一同学提问,在 Matt 反问后,那同学条件反射的回答『是』,会场才回到了了自由闲适的气氛。

而且,这个议题放在这里,个人感觉不是很合适,虽然都提到测试,但『此』测试『非彼』测试。另外,英文,可真是一个令人羞愧的问题,大多数的我们可与英文耳鬓厮磨了十几年啊,可连听个没有很多词汇的演讲都是如此吃力,就更别提『说』了(后面,见到一同学与 Matt 用英文自由的交谈,哇,顿时让我心声膜拜之意。心中也暗暗在想,这次回去后,要努力好好练习听说,别再『两天打渔三天晒网』)。

还有,不得不提一句有关于上午主会场的主持人,每个演讲者下去后发表的所谓的『评语』,听来要多做作就有做作,还有三个字,就不说了。

 

下午有分三个分论坛,每个分论坛又都有三场。当时报名我报的是分论坛二,而纵观每个分论坛的第一场,我是心仪于分论坛三,但最后『死』脑筋的我还是乖乖的呆在了分论坛二中(后面得知,其实是完全可以串场的,当然这又是后话了)。

第一场是趋势科技的张力做演讲, 主题是《我不是赤裸的羔羊––Web应用的安全性测试方法》。他先是列举了今年前面几起『有名的』在安全事故,如索尼的 SQL 注入, Google store 的 XSS 跨站攻击等。然后介他们所采用的发现应用程序漏洞的模糊测试,从识别威胁路径到识别威胁,到将威胁做笛卡尔乘积按优先级排序筛选后转化为测试用列,最后执行测试,并对测试做评估,中间还穿插了下 SQL 注入的演示实验。

会后感想:这场整个下来,感觉就好象一直围绕于 SQL 注入,并没真正的将『有关 Web 应用安全方面的测试方法』这个主题展开。演示实验时,还注意到提到 Web 提交的方式,他犹豫的说还有 POST(实例中是 GET) 等,这个『等』字实在有点让我惊讶(或许,是太紧张)。另外,演讲人本来应该也是想打造轻松活泼的气氛,所以 slides 里头几张在解说 『羔羊与恶狼』,以及还有 『地球很危险,我们还是回火星吧』 类似的动画图片。但可能真的他本人气场不够强大,以至现场飘过一声声尴尬的笑声。

 

中场休息过后,第二场开始。这场是腾讯的@吴凯华/jeremywu 带来的《腾讯互联网测试实践技术分享》,主要介绍了目前腾讯测试管理体系建设成果, 自动化+全方位电子流管理体系;全研发闭环流程;完善的计划、任务、用例、需求、度量统计等管理;其中创建的每个测试用例都需要评审,且 QA 评审时必须给出评审建议;评估项目风险时需要 coding 人员,产品以及测试人员一起来把控;度量需要根据项目团队,而不是根据组织,它是单元测试 + Code Review + 持续集成的工作。然后,还有介绍到一些他们使用到的工具如 testlink(测试管理平台), CI(持续集成平台), JSCoverage(自动检测加载的 JS), 这些都是开源,但他们都已进行过二次开发。

会后感想:这场真是太火爆,整个会场的空地都或站或坐着从论坛一和论坛二过来的同学(也是从这里,我才知道是可以串场的)。演讲完后的提问时间,同学们的兴致也很高,但主要都是围绕着度量和评估。应该是之前都有着这方面的困扰,所以想籍此机会多取点『经』吧。但怎么说,这真是个太大的命题,而且每个公司的组织结构也都不一样,兴许在『此』公司很好的管理方法,在『彼』公司并不一定行得通。

 

分论坛二的最后一场,是同济大学软件学院的@朱少民带来的《如何让缺陷无处藏身——谈软件可测试性》,主要介绍是如何让开发的软件具有可测试性,这其中提到需要分层、可定制等;根据需求建模,再由此生成测试用例;以及是在代码修改或是重构时,同样做到使软件具有可测试性。

部分问题整理
Q:对需求建模,是不是要求测试在产品策划前期就需要参与?
A:测试要测试产品的业务和功能,这就说明,产品策划阶段肯定是需要参与的。

Q:进行白盒测试,这说明是不是在开发期间,测试同样也是需要参与?
A:如果进行白盒测试,这代表需要清楚代码的结构,所以,最好是参与。

Q:测试人员对于设计模式,设计规则也要了解?
A:最好是测试,开发能互换角色,这样,测试的清楚开发的规则,而开发的,通过测试,能了解在开发中需要注意的各种问题。

Q:如何保证软件业务或是功能的完整?
A: 建个 checklist 。

Q:目前,管理软件方面基本上都是有以结果为导向的,有没有以过程导向的管理软件,包括国内外?
A:就我所了解,是还没有的,不如,我们合作开发一款吧。(这个回答让大家很 欢乐的笑了)

会后感想:不知道是不是因为整个社会浮躁的气氛,以至于大家都追求最直接的结果,就如最后那个问题中所提到的那样,以结果为导向。对于这场偏理论性方面的演讲,好大部分同学在会场要么堂而皇之的穿梭,要么窃窃私语或是昏睡或是干脆堂而皇之的离开,很少静下心来认认真真的听讲。不得不说,这样的心态,真是我们的一大悲哀。

 

另外分论坛一和三中老师和其演讲主题:

  • 朱磊 《大型互联网产品的性能原理分析与优化技巧》
  • 邱鹏/Ricky Qiu 《懒人的幸福生活 –––– 无人值守性能测试》
  • @王德山/耿电《大型性能评测模型和线上压测风险控制》
  • @倪生华 《分层自动化测试体系与持续集成实践》
  • 陈睿/竹权 《低碳淘宝,测试先行——淘宝核心系统软件测试实践》
  • 吴光安 《微软是如何测试的——云计算专场 》

这天下来,脑子还是有点疲劳,最主要原因是我测试方面的知识可以说是空白,每场都如同海绵吸水般,根本来不及消化。这里做下整理,希望在以后的工作中能快点上手。还有真的真的,英语急待提高,那场英文的演讲我听得多吃力只有自己清楚。

MySQL 连接

所谓连接查询,就是通过连接,使查询的数据从多个表中检索取得。在 SELECT 的 FROM 子句中写上所有有关的表名,就可以得到由几个表中的数据组合而成的查询结果。连接条件可在 FROMWHERE 子句中指定,WHEREHAVING 子句可包含其搜索条件,以供进一步筛选连接之后的结果集。 目前可实现的连接有:自然连接(Natural Join),内连接(Inner Join), 外连接(Outer Join), 交叉连接(Cross Join) etc.

JOIN USING 可按照指定的列实现表的等值连接。设有两个表t1, t2 具有相同的列 a, b, c, d, 如果不是对全部相同列做连接,而是是对列 a, b 做连接,可写成 t1 JOIN t2 USING(a,b)
JOIN ON 可按照更一般性条件实现表的等值连接。eg: t1(a, b), t2(a, c), 可写成 t1 JOIN t2 ON t1.a = t2.a
USING 后用于连接的列,也可用保留字 ON 指定, eg: ... USIGN(a)... 等价于 ... ON t1.a = t2.a..., 使用两者在结果集上体现的不同请见注 1

示例表 t1, t2, 其数据如下:

mysql> SELECT * FROM t1;
+---+------+
| a | b    |
+---+------+
| 1 | a    |
| 3 | c    |
| 5 | e    |
| 7 | g    |
+---+------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM t2;
+---+------+
| a | c    |
+---+------+
| 2 | b    |
| 4 | d    |
| 6 | f    |
| 7 | g    |
+---+------+
4 rows in set (0.00 sec)
自然连接
mysql> SELECT * FROM t1, t2 WHERE t1.a = t2.a;
+---+------+---+------+
| a | b    | a | c    |
+---+------+---+------+
| 7 | g    | 7 | g    |
+---+------+---+------+
1 row in set (0.00 sec)
内连接

mysql> SELECT * FROM t1 INNER JOIN t2 USING (a);
+—+——+——+
| a | b | c |
+—+——+——+
| 7 | g | g |
+—+——+——+
1 row in set (0.00 sec)
它等价于:SELECT * FROM t1, t2 WHERE t1.a = t2.a; or SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a;

外连接

外连接是连接的扩展。一般连接操作的结果表由符合连接条件的匹配元组连接起来的新元组构成,其余不符合连接条件的非匹配元组则被丢弃。外连接允许在结果表中保留非匹配元组,空缺部分填以NULL。其作用是在做连接操作时避免丢失信息。外连接有 3 类:
1 左外连接(Left Outer Join)。连接运算谓词为LEFT [OUTER] JOIN,其结果表中保留左关系的所有元组。eg:

mysql> SELECT * FROM t1 LEFT JOIN t2 USING(a);
+---+------+------+
| a | b    | c    |
+---+------+------+
| 1 | a    | NULL |
| 3 | c    | NULL |
| 5 | e    | NULL |
| 7 | g    | g    |
+---+------+------+
4 rows in set (0.00 sec)

等价于:SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a;

2 右外连接(Right Outer Join)。连接运算谓词为RIGHT [OUTER] JOIN, 其结果表中保留右关系的所有元组。MySQL 对其的优化策略见注 2

3 全外连接(Full Outer Join)。连接运算谓词为FULL [OUTER] JOIN, 其结果表中保留左右关系的所有元组。 MySQL 中, FULL JOIN... USING的结果集和INNER JOIN ... USING的结果集相同,且 MySQL 不支持 FULL OUTER JOIN。eg:

mysql> SELECT * FROM t1 FULL JOIN t2 USING(a);
+---+------+------+
| a | b    | c    |
+---+------+------+
| 7 | g    | g    |
+---+------+------+
1 row in set (0.00 sec)

mysql> SELECT * FROM t1 FULL OUTER JOIN t2 USING(a);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'OUTER JOIN t2 USING(a)' at line 1
交叉连接

交叉连接等同于做笛卡尔积。

mysql> SELECT * FROM t1 CROSS JOIN t2;
+---+------+---+------+
| a | b    | a | c    |
+---+------+---+------+
| 1 | a    | 2 | b    |
| 3 | c    | 2 | b    |
| 5 | e    | 2 | b    |
| 7 | g    | 2 | b    |
| 1 | a    | 4 | d    |
| 3 | c    | 4 | d    |
| 5 | e    | 4 | d    |
| 7 | g    | 4 | d    |
| 1 | a    | 6 | f    |
| 3 | c    | 6 | f    |
| 5 | e    | 6 | f    |
| 7 | g    | 6 | f    |
| 1 | a    | 7 | g    |
| 3 | c    | 7 | g    |
| 5 | e    | 7 | g    |
| 7 | g    | 7 | g    |
+---+------+---+------+
16 rows in set (0.00 sec)

它等价于:SELECT * FROM t1, t2; or SELECT * FROM t1 INNER JOIN t2;

注:

  • USING 和 ON 显示的结果说明
    为了使 MySQL 在解析 NATURAL JOINJOIN ... USING SQL 时采用 SQL 2003 的标准,从 MySQL 5.0.12 开始,这两种 SQL 的解析都有做调整, NATURAL JOIN 时, 查询结果中只会显示单独的唯一一列, 即 t1.a, t2.2 两列做自然连接后在结果中只有一列 a (= COELSCE(t1.a, t2.a)); 而 JOIN ... USING时,对 USING 中 指定使用做连接的列,查询结果中也只会显示单独的唯一一列, JOIN ... USING形式的变体如 LEFT JOIN ... USING, RIGHT JOIN ... USING 等解析优化也是采用同样的处理。除此之后,其他的连接方式还是遵照以前的规则。详细说明,可查看如下引用部分或MySQL 官方文档 JOIN Syntax一节。

    Join Processing Changes in MySQL 5.0.12
    Beginning with MySQL 5.0.12, natural joins and joins with USING, including outer join variants, are processed according to the SQL:2003 standard. The goal was to align the syntax and semantics of MySQL with respect to NATURAL JOIN and JOIN … USING according to SQL:2003. However, these changes in join processing can result in different output columns for some joins. Also, some queries that appeared to work correctly in older versions must be rewritten to comply with the standard.


    The single result column that replaces two common columns is defined using the coalesce operation. That is, for two t1.a and t2.a the resulting single join column a is defined as a = COALESCE(t1.a, t2.a), where:
    COALESCE(x, y) = (CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END)
    If the join operation is any other join, the result columns of the join consists of the concatenation of all columns of the joined tables. This is the same as previously.

    mysql> SELECT * FROM t1 LEFT JOIN t2 USING (a);
    +---+------+------+
    | a | b    | c    |
    +---+------+------+
    | 1 | a    | NULL |
    | 3 | c    | NULL |
    | 5 | e    | NULL |
    | 7 | g    | g    |
    +---+------+------+
    4 rows in set (0.01 sec)
    
    mysql> SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a;
    +---+------+------+------+
    | a | b    | a    | c    |
    +---+------+------+------+
    | 1 | a    | NULL | NULL |
    | 3 | c    | NULL | NULL |
    | 5 | e    | NULL | NULL |
    | 7 | g    |    7 | g    |
    +---+------+------+------+
    4 rows in set (0.01 sec)
    
  • 2右外连接的优化策略
    右外连接 SQL 在解析阶段都会转换为只包含左外连接的 SQL,一般遵循如下这样的转换方式:

    T1, ...) RIGHT JOIN (T2,...) ON P(T1,...,T2,...) =
    (T2, ...) LEFT JOIN (T1,...) ON P(T1,...,T2,...)
    

    有关其详细信息,请参考 MySQL 的官方文档7.3.1.10. Outer Join Simplification

    At the parser stage, queries with right outer joins operations are converted to equivalent queries containing only left join operations. In the general case, the conversion is performed according to the following rule:
    T1, …) RIGHT JOIN (T2,…) ON P(T1,…,T2,…) =
    (T2, …) LEFT JOIN (T1,…) ON P(T1,…,T2,…)

    通过EXPLAIN EXTENDED, SHOW WARNINGS, 查看 MySQL 解析优化后的右外连接:

    mysql> EXPLAIN EXTENDED SELECT * FROM t1 RIGHT JOIN t2 USING (a);
    +----+-------------+-------+--------+---------------+---------+---------+-----------+------+----------+-------+
    | id | select_type | table | type   | possible_keys | key     | key_len | ref       | rows | filtered | Extra |
    +----+-------------+-------+--------+---------------+---------+---------+-----------+------+----------+-------+
    |  1 | SIMPLE      | t2    | ALL    | NULL          | NULL    | NULL    | NULL      |    4 |   100.00 |       |
    |  1 | SIMPLE      | t1    | eq_ref | PRIMARY       | PRIMARY | 4       | test.t2.a |    1 |   100.00 |       |
    +----+-------------+-------+--------+---------------+---------+---------+-----------+------+----------+-------+
    2 rows in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS;
    +-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Level | Code | Message                                                                                                                                                            |
    +-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Note  | 1003 | select `test`.`t2`.`a` AS `a`,`test`.`t2`.`c` AS `c`,`test`.`t1`.`b` AS `b` from `test`.`t2` left join `test`.`t1` on((`test`.`t1`.`a` = `test`.`t2`.`a`)) where 1 |
    +-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
Tagged

May 2011 and Before Part III

  • 淘宝褚霸:leveldb性能分析和表现 http://t.cn/hDNi6Y
  • Nagios手册
  • grep 'test_string' filename.txt > /tmp/test.txt 表示将 filename.txt 中包含有 test_string 字符串行的定向输出到 /tmp 下 test.txt 文件中。
  • cp /usr/local/share/aclocal /usr/share
  • ps aux | grep 'application name'
  • 25 条 SSH 命令和技巧 [技巧] | Wow!Ubuntu http://t.cn/h4g30w
  • PDF 下载:最牛B的 Linux Shell 命令 [新闻] | Wow!Ubuntu http://t.cn/h47S1R
  • 石展:推荐神器:dstat,全能Linux系统信息#监控工具#,可直接替换vmstat, iostat, netstat ,nfsstat, ifstat等系统工具,监控cpu、disk 、mem、load、interrupt、net、proc、CS…. 界面见图也很美观. ubuntu下直接sudo apt-get install dstat ; redhat下wget http://t.cn/h1QrIy 安装即可 (tks Frost)
  • 淘宝褚霸:latencytop深度了解你的Linux系统的延迟 http://t.cn/hB2enj
  • 我对后端优化的一些感想关键字:优化, 响应时间,吞吐量,vmstat & iostat & netstat & tcprstat, strace & oprofile & systemtap, aspersa & latencytop & top, 空查询, Bloom filter etc。
  • 陈庆吉chenqj:写了两篇Facebook技术体系的介绍 http://t.cn/h4dkV0 http://t.cn/h4dkVR 都不算深入,大牛就别看了。
  • 唐福林:所谓服务,应该不分内外的 //@fishermen:对于内部调用者不能完全信任,至少增加一个内部appkey,便于跟踪、统计,同时在需要的时候可以轻松增加限制//@TimYang:内部公有服务如果没有管理机制哪些人调了确实很难跟踪,要升级或者纠错都找不到调用方在哪里。//@TimYang:淘宝的服务框架演变过程,林昊写的 http://t.cn/hGJ6wJ
  • Sina App Engine 数据存储服务架构 关键字:Apache, MySQL, PHP, Memecache etc, 有时间可看看。
  • IT技术博客大学习:《几种常见的基于Lucene的开源搜索解决方案对比》 几种常见的基于Lucene的开源搜索解决方案对比 … http://t.cn/hBmVz5
  • 淘叔度:nginx-0.9.5里面把listen的backlog由511调整为-1了。原因:linux内核里面listen系统调用的backlog是int型,但是在里面处理时会把它先转换成一个unsigned int再和系统设置的最大backlog进行比较,取二者的最小值。所以-1保证了永远取系统的最大值。backlog本来就是个hint值,系统默认是128。
  • suxiaoyong:再接上条: 8. 使用redis作为队列; 9. 尽量存储json数据,减少序列化开销; 10. 使用Mysql HandleSocket作为key value存储,cpu显著下降; 11. 数据过滤等交java中间件去做,减少数据库操作复杂性; 12. sns feed对数据完整性要求不高,必要时可以丢弃舍弃部分数据。//@suxiaoyong:接上条: 4. 在数据sharding时,对名博和普通用户分别处理; 5. sharding时采用两级分组,加强灵活性; 6. 使用DRBD做mysql实时同步; 7. 内容分发时,对于当前在线用户,使用redis的list作为cache,解决频繁请求时的刷新问题(相对于memcached也减少了内部通讯数据量);//@suxiaoyong:今天飞信首席架构师 @steadwater 关于sns feed的分享很不错,总结了一下,大概这些内容,不对的地方请补充: 1. 消息异步写入; 2. 推拉结合,对于粉丝多的用户用拉,普通用户用推,展示数据时进行合并; 3. 普通用户的事件尽量保证实时性,名博可以异步处理;
  • 可视化的数据结构和算法
  • 林信良常见算法笔记
  • ReflectionMethod PHP class, 获得指定的类的所有方法信息,详细信息,可PHP官方文档
  • 时蝇喜箭:深入理解PHP内核(TIPI)项目,也参考cnbeta文章: http://t.cn/IDa34O //@黄药师DE极致:转发微博@KimiChen:TIPI是一个开源项目,项目的初衷是为了分享有关PHP内部实现的方方面面,详情请点击http://t.cn/htWk9Y,强烈推荐之!
  • Faster Ruby
  • Node JS 资料
  • 我为什么向后端推荐 Node JS
  • node.js调研与服务性能测试
  • 惊喜就在这里
  • 关于前端 无意中发现的这个网站。
  • IE 6 调用 gzip 压缩后 Javascript 不能执行的问题, 出现这个 BUG 有可能是:服务器没有设置被请求文件(javascript)expries,cache-control; 服务器开启了 chunked encoding 模式; 通过 javascript 的 src 调用方式或者 AJAX 请求 javascript 文件等,解决是header 中:
    Cache-Control必须设置为 maxage=time 的格式, maxage 是指生存缓存生效时间, 1 为 1 秒;
    Expires 必须要设置,它的时间稍大于 Date(页面请求时间)即可;
    Pragma 必须设置为 public。
  • @Huihoo:Graffiti Markup Language (.gml) http://t.cn/hnJVu 涂鸦标记语言是基于XML的开放文件格式,用于存储涂鸦数据。互联网上很需要有一个大大的涂鸦墙,让我们有绘画的自由,思想表达的自由,精神发泄的自由。
  • 2010-12-30 MySQL 5.5正式版发布。
  • CSDN云计算:2011-03-17,据MongoDB官网消息,MongoDB v1.8.0已经发布。这是在2010年8月1.6版发布后的又一个版本。此次1.8版修复以往版本中的一些错误,并加入了许多新特性。 http://t.cn/IDtsI5
  • 淘叔度:Nginx是穷人家的孩子,品学兼优,任劳任怨,年级成绩第一的保持者,月薪要求1千块;Apache是地主家的孩子,多才多艺,班上的优秀学生干部,但抗压能力不够,月薪要求1万块;JBoss是富二代,后台很硬,见多识广,不能承受高压力且工作效率也不高,月薪要求3万块。作为老板的你会聘用哪个?
  • ora600ebay:DBA 1.0 掌握某主流商用RDBMS,例如Oracle。 DBA 2.0 = DBA 1.0+OS+Storage+Network+Application。 DBA 3.0 = DBA 2.0+MySQL (or Postgres etc)+NoSQL+Programmer。DBA 1.0/2.0 是Database management oriented, 而DBA 3.0是Data service oriented. DBA 1.0/2.0 是应用技术,DBA 3.0是创造技术。
  • jackbillow:Twitter也从syslog-ng转向了scribe,使用Hadoop来存储和分析数据。
  • 程序员幽默:【对程序员最具影响的,每个程序员都应该阅读的书籍】第1名《代码大全》第2名《程序员修炼之道》第3名《计算机程序的构造和解释》第4名《C程序设计语言》第5名《算法导论》第6名《重构:改善既有代码的设计》第7名《人月神话》第8名《设计模式》….全文见图或http://t.cn/h1HKmz

May 2011 and Before Part II

  • MangoDB doc
  • Foursqure: 使用 MongoDB Replica Sets 的三种架构
    在原有的 Master/Slave 机制上添加一台 arbiter;
    一个 Primary 用于写,多个 Secondary 用于读和一个 Secondary 用于备份;
    MongoDB 经典配置,上层是 Auto-Sharding, 每个 Sharding 结点 又是一个 Replica Sets。
  • tullyliu:内存占完后的,插入性能完全处于不可预测的状态,甚至会时快时慢,这个实在太无法接受了//@NinGoo:在@realzyy 的测试中,mongodb数据超过内存需要用到磁盘的时候,写入性能会有很大的下降,这是mmap的方式可以预期的。问题在于,每隔10s左右会有一个几乎跌到0的波动,原因尚待查证。
  • redis 运维的一些知识点
  • TimYang:1台机启动了2个Redis端口,另外两台机来测试写100字节,1台client跑到7万/秒, 一台client跑到9万/秒,加起来这台服务器每秒跑了16万次, 99.9%请求小于1ms。
  • Redis指令中文手册
  • Redis 容量及使用规划
  • TimYang:squid以文件操作为主,主要目的是静态化,当年开发时操作系统虚拟内存概念也没成熟。而Redis整个架构就是内存模型,所以如果app只使用操作系统内存,让操作系统来决定哪些是冷门的再swap,设计上是最自然的 //@童剑:主要看作者实现的如何了,Squid 不也是自己实现对象从内存到磁盘的交换吗,也挺好的。//@TimYang:再说下Redis数据需要全部放在RAM的问题,一个系统中热点数据的访问占总量一般小于20%,如果RAM要为这大部分冷门数据买单则是一种极大浪费。Redis VM设计思想就是把冷门数据交换到磁盘上,为热点数据腾出更多RAM空间。不过Redis绕过OS自己实现一套虚拟内存也具争议性。
  • TimYang:嗯,我的问题,强设了一下 echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse phpredis 每秒也能跑个1万多次 //@淘一啸:回复@淘叔度:多谢指点,一直没有认真研究状态图中的异常情况。不知道有没有方法能够通过程序来逐个验证。 //@淘叔度:我之前写过的一篇文章供参考:http://t.cn/hGjHeL//@TimYang:Which PHP Library to use with Redis? The Benchmark, 赢家是phpredis http://t.cn/hGlxWf。
  • yangwm:一个不错的redis presentation, http://t.cn/hGvsSl
  • TimYang:The (Redis) cluster project is currently not ready: even if we have a pretty clear design, and many networking level code for gossip and failure detection, it will take some more month to be released, and more time to be a stable release. 这就是用C开发分布式网络程//@摇摆巴赫:redis 作者新博客提出presharding的临时解决方案,早在这篇博客之前,杨教授 @TimYang 也提出过MPSS也正是这个想法,hash is easy,rehash is hard,我们可能每天都碰到类似的问题 here’s the simple solution , http://t.cn/h5G4nQ
  • iammutex:深入Redis内部-Redis 源码讲解 http://t.cn/h5dG1r 非常好的讲 Redis 内部实现及源码的文章~原文:http://t.cn/htpyGq
  • ackbillow:通过快照方式做replication在master数据量大时,整个过程会遇到一些问题,同时每次连接都才需要完整的一个快照。//@丹臣:今天配置了redis replication复制环境,redis salve异常挂掉,因为master有许多变更没有接收到,当slave重启后,会与master进行一次全同步,来保障数据的一致性。我实验的数据量很小,同步相当快。
  • 丹臣:@内涵帝,hset,减少了key储存的个数,在实际使用过程中,同一个key多个value值本来就要序列化的,一个key也只存一次的,并且value变长了,这样所需要的hash table管理结构就会减少,自然管理消耗的memory就会减少。本次测试用例是,数据长度太小,条数太多,导致管理空间成本很大//@丹臣:在有内存的情况下,redis每秒可以达到5w次tps get key[10bytes] value[10bytes],但19148251万object*(10bytes key length+10bytes value length)/1024/1024=365M,而redis-master用了3.3G的内存,管理结构成本相当大。http://t.cn/h1njF8
  • TimYang:更快的io设备写snapshot,其他都不是瓶颈。另外重启加载速度跟cpu相关。//@Birkoff:对@timyang 说:请教一下TimYang,Redis不开启VM的情况下,性能更多的取决于?1:更高频率的CPU 2:更大的CPU L2Cache 3:更快的内存?如何才能最大限度的发挥多核CPU的特性,提高Redis的处理能力?
  • TimYang:虽然LinkedIn经常发垃圾邮件,但是对其技术还是挺尊敬,Kafka, LinkedIn开源的pubsub的消息队列系统,其news feed也跑在这个系统上。 http://t.cn/hbjQIb。

May 2011 and Before Part I

  • ALTER TABLE tbl_name DROP PRIMARY KEY;, DROP INDEX idx_name ON tbl_name
  • MySQL HandleSocket技术在 SNS Feed存储中的应用
  • 为 MySQL 设置查询超时
  • Monitoring MySQL IO Latency with performance_schema
  • The fource categories of NoSQL databases
  • How to handler 1000′s of concurrent users on a 360MB VPS
  • FriendFeed Use MySQL 虽然已经是比较老的文章了,但还是值得一看。
  • MySQL 允许驼峰形式命令,my.cnf 中 mysqld 部分加入lower_case_table_names=2, 官方文档
  • MySQL binlog的地雷 5.1版本后,MySQL引入了基于ROW方式的binlog格式,不同于Statement方式的是,ROW方式记录了变更的内容,而不仅仅是SQL。
  • hellodba:推荐:《面向程序员的数据库访问性能优化法则》,作者是我们部门的架构师,即浅显易懂,又很有深度。http://t.cn/hbxlM9
  • 淘宝褚霸:MySQL的IO调优是个大工程,从Mysql->Innodb->Filesystem->Page/buffer->IO 调度器->raid一整条线路。
  • skip-name-reslove
  • 唐福林:UTF-8 String, mysql client latin1, mysql connect latin1, mysql db table utf-8, 存进去的中文,jdbc 怎么调参数,查出来还是乱码。 @Timyang 指示:convert(unhex(hex(convert(name using latin1))) using utf8) as name 太神奇了!
  • 时蝇喜箭:【关注】Stack Overflow 架构更新 (每月PV到9千5百万)http://t.cn/httWMr 有一节关于经验教训的,令人注目的一条:“Full Text Search in SQL Server is very badly integrated, buggy, deeply incompetent, so they went to Lucene.”
  • sagasw大连程序员 :分享 Designing for Error (2) http://t.cn/h5iVdJ http://t.cn/htwNUo
  • jackbillow:Nick Kallen提到的几个设计思想:1. 没有银弹,所有的解决方案都是暂时的。2.可扩展性涉及分区,索引(不仅仅指的db中key的概念)和复制。3.所有的数据都在内存里,磁盘仅仅是落地。4.预估能解决一些问题,但很多问题也不是前期设计能预料的。5.尽可能的使用本地化策略譬如:cache本地化或就近访问。
  • ylinn:回复@NinGoo:可以设置直接使用remote 内存,避免swap //@NinGoo:间在mysql等大内存环境下,NUMA个节点间的内存使用难以均衡,在其他节点还有可用内存的情况下,某个节点内存不足也可能导致swap的产生,而swap是数据库头疼的大问题之一。//@Fenng:NUMA架构对DB产生的问题,是MySQL扩展性的绊脚石之一
  • FusionioChina:Facebook 的mySQL 大拿关于Mastering innoDB diagnostics. http://t.cn/hdmJES
  • 唐福林:原来 memcache 也就只检查 50 个key,学习了//@唐福林:@zhangwei217245 @摇摆巴赫 @TimYang Redis 默认的 LRU 算法,只检查 3 个key,从中间挑一个最长时间未使用的就删除?//@唐福林:Redis这么使用LRU? LRU and minimal TTL algorithms are not precise algorithms but approximated algorithms (in order to save memory), so you can select as well the sample size to check. For instance for default Redis will check three keys and pick the one that was used less recently
  • fengyuncrawl:#数据分布算法#1)Round-Robin法 2)Hash法 3)Range法 4)Replicate法。目前还没有一种数据分布方法能够优化所有情况的数据查询,另外,就算能找到一种良好的数据分布策略在系统初始的情况下达到最优,但是随着系统的运行,数据不断更新这种最优平衡一定会被打破。根据实际情况选择合适动态分布策略
  • tb丁原:同等硬件环境下,相比redis,tair,search,oceanbase,hbase等,oracle,mysql性能看起来总是差了一些,其实不管什么软件,设计思路上不外乎内存读写,顺序读写,顺序写随机读,随机写顺序读,随机读随机写这几种,还能有什么?
  • 微软中国MSDN:【批量操作SQL数据】我们在已经建好触发器的表中对数据进行一个批量更新操作的时候,系统会提示我们无法完成操作,这个时候就需要我们先将触发器停掉,然后再进行UPDATE操作,完后再开启触发器。alter table tablename disable trigger all 批处理的SQL语句 alter table tablename enable trigger all。

设计模式 and OOD

推荐两篇值得仔细阅读的关于架构方面的文章,都是出自 Code Porject 上的 Al-Farooque Shubho 之手。

这两篇文章,倪大虾 同学已经翻译,看中文,移步这里:

Tagged

MySQL 压力测试工具 mysqlslap

FROM: MySQL 压力测试工具 mysqlslap

从 5.1.4 开始,MySQL 自带有一个压力测试工具 mysqlslap, 它通过模拟多个并发客户端访问 MySQL 来执行测试,使用起来非常简单。通过mysqlslap --help可以获得可用的选项,这里列一些主要的参数,更详细的说明参考官方手册

  • --auto-generate-sql, -a 自动生成测试表和数据。
  • --auto-generate-sql-load-type=type 测试语句的类型。取值包括:read,key,write,update和mixed(默认)。
  • --number-char-cols=N, -x N 自动生成的测试表中包含多少个字符类型的列,默认 1。
  • --number-int-cols=N, -y N 自动生成的测试表中包含多少个数字类型的列,默认 1。
  • --number-of-queries=N 总的测试查询次数(并发客户数×每客户查询次数)。
  • --query=name,-q 使用自定义脚本执行测试,eg: 可以调用自定义的一个存储过程或者 SQL 语句来执行测试。
  • --create-schema 指定测试的数据库。
  • --commint=N 多少条 DML 后提交一次。
  • --compress, -C 如果服务器和客户端支持都压缩,则压缩信息传递。
  • --concurrency=N, -c N 并发量,也就是模拟多少个客户端同时执行 SELECT。可指定多个值,以逗号或者--delimiter参数指定的值做为分隔符。
  • --engine=engine_name, -e engine_name 创建测试表所使用的存储引擎,可指定多个。
  • --iterations=N, -i N 测试执行的迭代次数。
  • --detach=N执行 N 条语句后断开重连。
  • --debug-info, -T打印内存和CPU的信息。
  • --only-print 只打印测试语句而不实际执行。
  • --defaults-file=mysql_configuration_file_directory 配置文件存放位置。
  • --socket=socket_directory, -S socket_directory socket文件位置。

测试的过程需要生成测试表和测试数据,mysqlslap 会自动生成一个名为 mysqlslap 的 schema,如果已经存在则先删除。可用--only-print来打印实际的测试过程。

[root@localhost bin]# /usr/local/mysql/bin/mysqlslap -a --only-print
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE `t1` (intcol1 INT(32) ,charcol1 VARCHAR(128));
INSERT INTO t1 VALUES (1804289383,'mxvtvmC9127qJNm06sGB8R92q2j7vTiiITRDGXM9ZLzkdekbWtmXKwZ2qG1llkRw5m9DHOFilEREk3q7oce8O3BEJC0woJsm6uzFAEynLH2xCsw1KQ1lT4zg9rdxBL');
......
DROP SCHEMA IF EXISTS `mysqlslap`;

可以看出,最后会删除一开始创建的 schema,so, 整个测试完成后不会在数据库中留下痕迹。
假如执行一次测试,分别模拟 50 和 100 个并发,都执行 1000 次查询,那么:

[root@localhost bin]# /usr/local/mysql/bin/mysqlslap -a --concurrency=50,100 --number-of-queries=1000 --debug-info
Benchmark
        Average number of seconds to run all queries: 0.676 seconds
        Minimum number of seconds to run all queries: 0.676 seconds
        Maximum number of seconds to run all queries: 0.676 seconds
        Number of clients running queries: 50
        Average number of queries per client: 20

Benchmark
        Average number of seconds to run all queries: 0.922 seconds
        Minimum number of seconds to run all queries: 0.922 seconds
        Maximum number of seconds to run all queries: 0.922 seconds
        Number of clients running queries: 100
        Average number of queries per client: 10

User time 0.17, System time 0.40
Maximum resident set size 0, Integral resident set size 0
Non-physical pagefaults 1653, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 14740, Involuntary context switches 6135

Voluntary context switches 7319, Involuntary context switches 681

上结果可以看出,50 和 100 个并发分别得到一次测试结果(Benchmark),并发数越多,执行完所有查询的时间越长。为了准确起见,可以多迭代测试几次:

[root@localhost bin]# /usr/local/mysql/bin/mysqlslap -a --concurrency=50,100 --number-of-queries=1000 --iterations=5  --debug-info
Benchmark
        Average number of seconds to run all queries: 0.833 seconds
        Minimum number of seconds to run all queries: 0.803 seconds
        Maximum number of seconds to run all queries: 0.865 seconds
        Number of clients running queries: 50
        Average number of queries per client: 20

Benchmark
        Average number of seconds to run all queries: 0.980 seconds
        Minimum number of seconds to run all queries: 0.948 seconds
        Maximum number of seconds to run all queries: 1.007 seconds
        Number of clients running queries: 100
        Average number of queries per client: 10

User time 1.03, System time 2.35
Maximum resident set size 0, Integral resident set size 0
Non-physical pagefaults 7148, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 115255, Involuntary context switches 4125

测试同时不同的存储引擎的性能进行对比:

[root@localhost bin]# /usr/local/mysql/bin/mysqlslap -a --concurrency=50,100 --number-of-queries=1000 --iterations=5 --engine=myisam,innodb  --debug-info
Benchmark
        Running for engine myisam
        Average number of seconds to run all queries: 0.781 seconds
        Minimum number of seconds to run all queries: 0.766 seconds
        Maximum number of seconds to run all queries: 0.800 seconds
        Number of clients running queries: 50
        Average number of queries per client: 20

Benchmark
        Running for engine myisam
        Average number of seconds to run all queries: 0.908 seconds
        Minimum number of seconds to run all queries: 0.880 seconds
        Maximum number of seconds to run all queries: 0.929 seconds
        Number of clients running queries: 100
        Average number of queries per client: 10

Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 0.897 seconds
        Minimum number of seconds to run all queries: 0.858 seconds
        Maximum number of seconds to run all queries: 0.929 seconds
        Number of clients running queries: 50
        Average number of queries per client: 20

Benchmark
        Running for engine innodb
        Average number of seconds to run all queries: 1.189 seconds
        Minimum number of seconds to run all queries: 1.086 seconds
        Maximum number of seconds to run all queries: 1.306 seconds
        Number of clients running queries: 100
        Average number of queries per client: 10

User time 2.02, System time 4.24
Maximum resident set size 0, Integral resident set size 0
Non-physical pagefaults 14556, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 172917, Involuntary context switches 52011

100 个并发时,InnoDB 引擎,运行 1000 句 SQL 平均要需要 1.189 秒;而对于 MyISAM, 为 0.908 秒。

测试自定义 SQL:

[root@localhost bin]# /usr/local/mysql/bin/mysqlslap --defaults-file=/usr/local/mysql/etc/my.cnf --create-schema=hstestdb --concurrency=50,100 --number-of-queries=1000 --iterations=5 --query="SELECT * FROM hstestdb.hstesttbl WHERE k='k2'"  --debug-info -u root -p -S /usr/local/mysql/tmp/mysql.sock
Enter password:
Benchmark
        Average number of seconds to run all queries: 0.271 seconds
        Minimum number of seconds to run all queries: 0.256 seconds
        Maximum number of seconds to run all queries: 0.288 seconds
        Number of clients running queries: 50
        Average number of queries per client: 20

Benchmark
        Average number of seconds to run all queries: 0.324 seconds
        Minimum number of seconds to run all queries: 0.292 seconds
        Maximum number of seconds to run all queries: 0.333 seconds
        Number of clients running queries: 100
        Average number of queries per client: 10

User time 0.22, System time 0.63
Maximum resident set size 0, Integral resident set size 0
Non-physical pagefaults 4355, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 16691, Involuntary context switches 2837
Tagged