在线年龄查询器(傅老师-大数据分析与挖掘综合能力提升实战)
在线年龄查询器文章列表:
- 1、傅老师-大数据分析与挖掘综合能力提升实战
- 2、时代霸主——微软总裁比尔·盖茨
- 3、PostgresSql学习-Vacuum清理机制
- 4、大话数据库MySQL项目实战的那几个点
- 5、大话数据库MySQL项目实战的那几个点
傅老师-大数据分析与挖掘综合能力提升实战
大数据分析与挖掘综合能力提升实战
【课程目标】
本课程为大数据分析初级课程,面向所有应用型人员,包括业务部门,以及数据分析部门,系统开发人员也同样需要学习。
本课程核心内容是理清大数据的本质及核心理念,培训大数据人才的数据思维模式,以解决业务问题为导向,提升学员的数据分析综合能力。
本课程覆盖了如下内容:
1、 大数据的本质,核心数据思维。
2、 数据分析过程,数据分析工具。
3、 数据分析方法,数据分析思路。
4、 数据可视呈现,数据报告撰写。
本课程从实际的业务需求出发,结合行业的典型应用特点,围绕实际的商业问题,对数据分析及数据挖掘技术进行了全面的介绍(从数据收集与处理,到数据分析与挖掘,再到数据可视化和报告撰写),通过大量的操作演练,帮助学员掌握数据分析和数据挖掘的思路、方法、表达、工具,从大量的企业经营数据中进行分析,挖掘客户行为特点,帮助运营团队深入理解业务运作,以达到提升学员的数据综合分析能力,支撑运营决策的目的。
通过本课程的学习,达到如下目的:
1、 了解数据分析基础知识,掌握数据分析的基本过程。
2、 学会数据分析的框架和思路,掌握常用数据分析方法来分析问题。
3、 熟悉数据分析的基本过程,掌握Excel高级数据分析库操作。
4、 熟悉大数据分析工具Power BI,提升数据分析效率,避免重复工作。
【授课时间】
2天时间(每天6个小时)
【授课对象】
销售部门、营业厅、呼叫中心、业务支撑、经营分析部、网管/网优中心、运营分析部、系统开发部等对业务数据分析有基本要求的相关人员。
【学员要求】
1、 每个学员自备一台便携机(必须)。
2、 便携机中事先安装好Excel 2013版本及以上。
3、 便携机中事先安装好Power BI Desktop软件。
注:讲师可以提供试用版本软件及分析数据源。
【授课方式】
数据分析基础 方法讲解 实际业务问题分析 Excel实践操作
采用互动式教学,围绕业务问题,展开数据分析过程,全过程演练操作,让学员在分析、分享、讲授、总结、自我实践过程中获得能力提升。
【课程大纲】
第一部分: 大数据的核心思维
问题:大数据的核心价值是什么?大数据是怎样用于业务决策?
1、 大数据时代:你缺的不是一堆方法,而是大数据思维
2、 大数据的本质
Ø 数据,是对客观事物的描述和记录
Ø 大数据不在于大,而在于全
3、 大数据四大核心价值
Ø 用趋势图来探索产品销量规律
Ø 从谷歌的GFT产品探索用户需求变化
Ø 从大数据炒股看大数据如何探索因素的相关性
Ø 阿里巴巴预测经济危机的到来
Ø 从美国总统竞选看大数据对选民行为进行分析
4、 大数据价值落地的三个关键环节
Ø 业务数据化
Ø 数据信息化
Ø 信息策略化
案例:喜欢赚“差价”的营业员(用数据管理来识别)
第二部分: 数据分析基本过程
1、 数据分析简介
Ø 数据分析的三个阶段
Ø 分析方法的三大类别
2、 数据分析六步曲
3、 步骤1:明确目的--理清思路
Ø 确定分析目的:要解决什么样的业务问题
Ø 确定分析思路:分解业务问题,构建分析框架
4、 步骤2:数据收集—准备数据
Ø 明确收集数据范围
Ø 确定收集来源
Ø 确定收集方法
5、 步骤3:数据预处理—准备数据
Ø 数据质量评估
Ø 数据清洗、数据处理和变量处理
Ø 探索性分析
6、 步骤4:数据分析--寻找答案
Ø 选择合适的分析方法
Ø 构建合适的分析模型
Ø 选择合适的分析工具
7、 步骤5:数据展示--观点表达
Ø 选择恰当的图表
Ø 选择合适的可视化工具
8、 步骤6:报表撰写--观点表达
Ø 选择报告种类
Ø 完整的报告结构
9、 演练:终端大数据精准营销案例赏析
Ø 如何搭建精准营销分析框架?
Ø 精准营销分析的过程和步骤?
Ø 精准营销分析结果呈现
第三部分: 统计分析方法实战篇
问题:数据分析有什么方法可依?不同的方法适用解决什么样的问题?
1、 数据分析方法的层次
Ø 描述性分析法(对比/分组/结构/趋势/交叉…)
Ø 相关性分析法(相关/方差/卡方…)
Ø 预测性分析法(回归/时序/决策树/神经网络…)
Ø 专题性分析法(聚类/关联/RFM模型/…)
2、 统计分析基础
Ø 统计分析两大要素
Ø 统计分析三个步骤
3、 统计分析常用指标
Ø 汇总方式:计数、求和、百分比(增跌幅)
Ø 集中程度:均值、中位数、众数
Ø 离散程度:极差、方差/标准差、IQR
Ø 分布形态:偏度、峰度
4、 基本分析方法及其适用场景
Ø 对比分析(查看数据差距)
演练:寻找用户的地域分布规律
演练:寻找公司主打产品
演练:用数据来探索增量不增收困境的解决方案
案例:银行ATM柜员机现金管理分析(银行)
Ø 分组分析(查看数据分布)
案例:排班后面隐藏的猫腻
案例:通信运营商的流量套餐划分合理性的评估
演练:银行用户消费层次分析(银行)
演练:呼叫中心接听电话效率分析(呼叫中心)
演练:客服中心科学排班人数需求分析(客服中心)
演练:客户年龄分布/消费分布分析
Ø 结构分析(评估事物构成)
案例:用户市场占比结构分析
案例:物流费用占比结构分析(物流)
案例:中移动用户群动态结构分析
演练:用户结构/收入结构/产品结构的分析
Ø 趋势分析(发现事物随时间的变化规律)
案例:破解零售店销售规律
案例:手机销量的淡旺季分析
演练:发现产品销售的时间规律
Ø 交叉分析(多维数据分析)
演练:用户性别 地域分布分析
演练:不同区域的产品偏好分析
演练:不同教育水平的业务套餐偏好分析
5、 综合分析方法及其适用场景(略)
Ø 综合评价法(多维指标归一)
案例:南京丈母娘选女婿分析表格
演练:人才选拔评价分析(HR)
Ø 杜邦分析法(关键因素分析-财务数据分析)
案例:运营商市场占有率分析(通信)
案例:服务水平提升分析(呼叫中心)
演戏:提升销量的销售策略分析(零售商/电商)
Ø 漏斗分析法(关键流程环节分析-流失率与转化率分析)
案例:电商产品销售流程优化与策略分析(电商)
演练:营业厅终端销售流程分析(电信)
演练:银行业务办理流程优化分析(银行)
Ø 矩阵分析法(产品策略分析-象限图分析法)
案例:工作安排评估
案例:HR人员考核与管理
案例:波士顿产品策略分析
6、 最合适的分析方法才是硬道理。
第四部分: 数据分析思路篇
问题:数据分析思路是怎样的?如何才能全面/系统地分析而不遗漏?
1、 常用分析思路模型
2、 企业外部环境分析(PEST分析法)
案例:电信行业外部环境分析
3、 用户消费行为分析(5W2H分析法)
案例讨论:搭建用户消费习惯的分析框架(5W2H)
4、 公司整体经营情况分析(4P营销理论)
5、 业务问题专题分析(逻辑树分析法)
案例:用户增长缓慢分析
6、 用户使用行为研究(用户使用行为分析法)
案例:终端销售流程分析
第五部分: 数据分析策略
问题:数据多,看不明白,不知道从何处看出业务问题?
1、 数据分析策略
Ø 先宏观,后微观
Ø 先整体,再部分
Ø 先普遍,再个别
Ø 先单维,再多维
Ø 先表象,再根因
Ø 先过去,再未来
2、 数据解读要诀
Ø 看差距,找短板
Ø 看极值,评优劣
Ø 看分布,分层次
Ø 看结构,思重点
Ø 看趋势,思重点
Ø 看峰谷,找规律
Ø 看异常,找原因
3、 解读要符合业务逻辑
案例:营业厅客流趋势分析
第六部分: 数据呈现(根据需要讲解,课件留给学员参考)
1、 常用图形类型及选择原则
2、 基本图形画图技巧
3、 图形美化原则
4、 表格美化技巧
案例:绘图示例
第七部分: 分析报告撰写(根据需要讲解,课件留给学员参考)
问题:如何让你的分析报告显得更专业?
1、 分析报告的种类与作用
2、 报告的结构
3、 报告命名的要求
4、 报告的目录结构
5、 前言
6、 正文
7、 结论与建议
第八部分: Power Query预处理工具实战篇
1、 Power BI组件框架
Ø Power Query超级查询器
Ø Power Pivot超级透视表
Ø Power view交互式图表工具
2、 获取和转换(Power Query)
Ø 数据处理的常见问题
Ø PQ功能简介
3、 多数据源读取
Ø 多数据源读取
演练:从文件/Excel/数据库/Web页获取数据源
4、 数据组合/集成
Ø 数据的追加
Ø 变量的合并
Ø 文件夹合并
演练:数据集成(追加、合并、文件夹)
5、 数据转换
Ø 数据表的管理
Ø 数据类型和格式
Ø 数据列的操作
Ø 数据行的操作
演练:数据预处理操作
6、 PQ的本质—M语言
Ø 强大的M语言
第九部分: Power View交互式图表工具实战篇
问题:如何让你的分析结果更直观易懂?如何让数据“慧”说话?
1、 图表类型与作用
2、 常用图形及适用场景
3、 Power view简介
4、 常用图表制作
Ø 柱状图、条形图
Ø 折线图、饼图
5、 复杂图形制作
Ø 双坐标图(不同量纲呈现)
Ø 对称条形图(对比)
Ø 散点图/气泡图(矩阵分析法)
Ø 瀑布图(成本、收益构成分析)
Ø 漏斗图(用户转化率分析)
演练:图表制作与演示
6、 交互式图表
7、 分层钻取
8、 四种筛选器
第十部分: Power Pivot数据建模工具实战篇
1、 Power Pivot简介
2、 PP基本功能
Ø 数据分类
Ø 汇总方式
3、 超级透视表
Ø 建模的核心:筛选器与计算器
Ø 建立多表关系模型
Ø 关系管理:新建、修改、删除
演练:数据预处理操作
4、 度量值
Ø 度量值定义
Ø 度量值计算
Ø 度量值的双层筛选
演练:度量值使用
5、 计算列
Ø 新建列
Ø 列与度量值的区别
6、 DAX数据分析表达式
Ø DAX公式
Ø DAX运算符
Ø DAX函数
Ø DAX高级筛选函数
7、 上下文
Ø 行上下文
Ø 筛选上下文
Ø 度量值的计算原理
Ø 上下文冲突时的上下文处理
结束:课程总结与问题答疑。
-
傅老师 华为系大数据专家
计算机软件与理论硕士研究生(研究方向:数据挖掘、搜索引擎)。在华为工作十年,五项国家专利,在华为工作期间获得华为数项奖项,曾在英国、日本、荷兰和比利时等海外市场做项目,对大数据有深入的研究。
傅老师专注于大数据分析与挖掘、机器学习等应用技术,以及大数据系统部署解决方案。旨在将大数据的数据分析、数据挖掘、数据建模应用于行业及商业领域,解决行业实际的问题。
欢迎联系咨询更多老师资料,私信约老师上课!
时代霸主——微软总裁比尔·盖茨
全球个人电脑软件领导品牌——微软公司的董事长兼CEO。
比尔·盖茨出生于1955年10月28日,和二位姐妹一同在西雅图成长。父亲是一位律师,已去世的母亲则是位集学校老师、华盛顿大学董事长和United Way international事长等职务于一身的女性。
13岁时,盖茨在私立的湖滨学校接触电脑并开始了未来的事业——个人电脑软件与设计电脑程式。
1993年,盖茨进入哈佛大学。大三那年,盖茨离开哈佛,专心致力于微软的工作。
主要业绩
●自1996年夏天开始到1997年,微软的市场价值上升了119%,达到1580亿美元。
●1997年6月为止的会计年度,微软营业额为113亿美金,员工遍布58个国家,并多达2.5万人。
●1999年6月,微软市场价值达到4072.2亿美元,名列全球1000大企业榜首,超过了通用电气公司(3330.5亿美元)。
管理精粹
●"你从来赢不了,你只是想生产更好的产品。"
●"'让我们去赢吧'或是'我们已经赢了',那就将意味着我们的追求有终点。"比尔·盖茨对微软的员工说。
"以常人不可企及的才干带领微软实现成功转型。"
商业周刊1996
时代霸主
盖茨的成功源于杰出的才智、坚韧不拔的追求、顽强的竞争意识和全身心的投入。这也是微软公司的特点。盖茨的个性决定了微软的企业文化。
盖茨喜欢这一切。智力挑战是乐趣。运动是乐趣。猜谜是乐趣。而与聪明的人一起工作则是超级乐趣。其他人也许认为他冷酷无情甚至残忍;但对他而言,商业竞争就像体育比赛,或许是一场流血的体育比赛。
"你从来赢不了,你只是生产更好的产品,……你从来不会听到在微软的会议中有人说:'让我们去赢吧'或是'我们已经赢了',因为那将意味着我们的追求有终点。"
当比尔·盖茨(Bill Gatas)上小学6年级的时候,他的父母认为有必要带他去看心理医生,因为他和母亲的关系搞得很紧张。他的母亲名叫玛丽,是一个性格随和的女性,她觉得儿子应该听从她。比尔·盖茨当时住在一个地下室的卧室里,卧室脏乱不堪,母亲也无法帮他收拾干净,后来干脆不管了。有时母亲来叫他吃饭,他也不搭理。有一次她通过家庭对讲机问:"你在干什么?"
"我在思索,"他气呼呼地说,"你是否曾经思索过?"
经过一年的咨询和一系列测试,医生终于得出了结论,他告诉玛丽;"你输了。我也拿他没辙。你最好还是学着面对现实吧。"玛丽是个很好强的聪明人,她丈夫回忆说:"但她不得不承认,和儿子竞争是徒劳的。"
很多计算机公司也得出了同样的结论。盖茨从哈佛辍学以来21年内,创立了微软公司。现年41岁的他已经击败了桌面操作系统和应用软件方面的竞争对手。如今他正雄心勃勃,准备将微软公司发展为一家媒体信息公司。
在此过程中,他聚敛了364亿美元的巨额财富。自1996年夏天以来,微软的市场价值上升了119%,达到1580亿美元,从而使盖茨的财富增加了180亿美元,相当于日进5000万美元。盖茨稳居世界头号富翁的宝座,但他拥有的还不仅仅是钱财。用《时代》周刊的话说,他已成为当今时代的爱迪生和福特。他从技术人员成长为企业家,象征了数字化时代。
他的成功源于杰出的才智、坚韧不拔的追求、顽强的竞争意识和全身心的投入。这也是微软公司的特点。比尔·盖茨的个性决定了微软的企业文化。然而,尽管他已成为世界上最著名的商人,除了在少数几个亲密朋友面前,盖茨却始终保持着一份神秘。
盖茨的神秘部分来自于他的睿智。在微软,人们使用计算机术语描述这一点:盖茨拥有"令人难以置信的处理能力"和"无限的带宽",他十分擅长"并行处理"和"多任务处理"。只要看看他的办公桌就明白了。盖茨同时在两台计算机上工作,一台从互联网络中连续不断地获得数据,另一台处理着上百封电子邮件和备忘录,把他的大脑与网络联成一体。他加工提炼信息的能力实在惊人,也许他的思维真是数字化的:没有脆弱的感情,没有含混的模拟状态,只有数十亿的二进位脉冲、冷静地将输入转化成正确的答案。
"我认为人类的智慧没有任何独特之处,"盖茨第一次与《时代》周刊记者共进晚餐时说,"大脑中的所有形成知觉和情感的神经元都是以二进制的方式运作的,有一天我们可以在机器上复制它们。"地球上的生命都是由碳构成的,而电脑则是由硅构成的,但那不算是最重要的区别。"总有一天,我们能够给人类基因组排序,复制自然界在以碳为基础的系统中形成的智力。"盖茨承认这种想法有点吓人,但他打趣说它也可能带有一点自欺欺人的味道。"这有点像倒序制造,即拿到别人的产品再根据拆开的机件进行仿制。"
盖茨的灵魂有没有特异之处?探索其证据可能是一个很大的挑战。
◇痴迷计算机
"当他还是一个婴儿的时候,他就习惯于在摇篮里摇来摇去,"盖茨的父亲回忆说。这位退休的律师仍然住在盖茨从小长大的房子里。盖茨的母亲玛丽"是一位出色的女人",老盖茨说。作为一个银行家的女儿,她在社交和商业上游刃有余,做过许多机构的董事。她1994年去世以后,西雅图以她的名字命名了一条街道。
"三点(老盖茨对小盖茨的爱称,源于三点的纸牌)在社交场合缺乏自信。我还记得他为了邀请一个女孩去参加学校舞会愁了整整两个星期,最后还是被拒绝了。他妈妈却不是这样。她是一位社文明星……"老盖茨拿出一些玛丽的照片。她和儿子都喜欢玩牌,在全家团聚的盛宴之后,他们会打桥牌,做猜谜游戏。"这样的游戏可不是闹着玩的,"老盖茨说。"输赢关系重大。"
盖茨有一个姐姐和一个妹妹。姐姐克里斯蒂长他一岁,是微软公司的税务会计。妹妹莉比小他9岁,住在离娘家不远的地方,正在抚养两个幼小的孩子。父亲回忆说:"我们一家都喜欢运动。星期六我们举行网球邀请赛,而星期天则是家庭奥运会,有各种各样的项目。三点更喜欢个人项目,如滑水,而不是集体项目。"1986年,微软成功以后,盖茨为他的家人建了一个名叫Cateaway的度假营,在那里,父母和他重温旧日时光,只不过这次游戏的规模扩大了,一些朋友和微软的职工也加入进来。除了通常的项目外,总有一些智力游戏和表演。
盖茨要升初中的时候,父母很为他发愁。他个头很小,又生性腼腆,十分需要保护。况且他的兴趣与6年级的同龄孩子迥然不同,因此,父母决定送他到一所有名的私立中学就读。公立学校很可能无法满足他的智力发展。
在湖畔中学里,盖茨迷上了一台笨拙的计算机终端。它是湖畔中学母亲俱乐部捐献的。这些母亲们决定,把一次义卖所得的钱用来为学生们安装一台终端机,并为他们支付机时费。还在60年代末的西雅图,就让学生使用计算机,这是非常罕见的——事实证明,它对盖茨的成长起了非常重要的作用。
盖茨与同伴保罗·艾伦(Paul Allen)一道从操作手册上学会了BASIC语言。在8年级时,盖茨写出了他的第一个软件程序,目的是为了玩三连棋。这之后,盖茨读到了拿破仑的军事战略,受其启发,他设计了一种叫做"冒险"的计算机游戏。这一游戏的目标是统治世界。
盖茨和艾伦不久就开始利用晚上的时间为一家当地公司干活。这家公司买了一台DEC计算机,艾伦、盖茨及其他孩子被它雇来寻找计算机程序中的错误。更好的说法也许是公司"允许"他们使用计算机,因为孩子们得不到报酬,纯粹是为了好玩儿。这家公司愿意这样做,因为它与DEC公司签有合同,只要能找出DEC软件中的"臭虫",就不必为使用DEC计算机而付费。
DEC的软件程序是新开发出来的,很复杂,难免存在不少错误。DEC公司与用户签这种合同是软件公司的一种常见做法,意在发现软件中最细微的缺陷。半年下来,孩子们收获甚丰,盖茨的成绩尤为突出。他们根据自己的工作编纂的《问题报告书》,最后长达300页。DEC终止了合同,盖茨后来回忆说:"DEC发现,这帮家伙总能挑出毛病。"
而父亲记得,盖茨对此事十分着迷。"三点会在我们睡下以后,偷偷溜出卧室,在计算机旁呆上大半夜。"计算机方面显示的才干使盖茨脱胎换骨,成为一位自信心十足的年轻商人。上高中的时候,英特尔8008芯片问世,艾伦和盖茨花360美元买了一块,用这块小芯片启动一台机器。该机器可以分析城市道路交通监视器传来的信息。许多市政当局测量交通流量都采用这样的办法:在一条选定的街道上拉一条橡胶软管,当车辆通过软管时,它便撞击了位于软管尾端的金属箱中的带子,并打印出图形和其他数据。他为自己的新公司取名为交通数据公司(Trof o'Data),盖茨说,"那时它听起来像诗一样。"
交通数据公司并没有获得成功,也许是因为市政当局不愿意从两个毛头小子手中购买设备。那一年,艾伦19岁,盖茨16岁,不过看起来比实际年龄还要年轻。
"他的自信心和幽默感都增强了,"父亲回忆说。"他成了一位故事大王,能够模仿每个人的声音,并且同母亲也讲和了。"
◇软件下面有黄金
"9年级的时候,"盖茨回忆说,"我开始了一种新的反叛。我的成绩不算好,但我决定在不带一本书回家的情况下使功课门门都达到A。我不去上数学课,因为我已经自学了很多内容,在全国性的能力测试中名列十佳。这使我学会了独立,并懂得了我不再需要反抗任何人。"到了10年级,他开始传授计算机知识,并为学校编写学生座次排序软件。他偷偷加进一些指令,使自己成为班上几乎唯一一个周围坐满女生的男孩。
和艾伦一起,他建立了听起来像模像样的"湖畔编程小组",为当地公司开发软件。当艾伦企图独自承揽业务时,盖茨同他发生了第一次争吵。但艾伦很快发现工作起来不知疲倦的盖茨是不可缺少的,重又邀请盖茨回来工作。"我回来工作可以,"盖茨告诉艾伦,"但我要当负责人。我会习惯当负责人的,从现在开始,与我打交道会很难缠,除非我当负责人。"
两人学到了更多的计算机技能,并且发现,这些技能可以为自己带来丰厚的收入。盖茨买了一艘快艇,两人常常一同前往附近的湖中兜风。
他们过了一年半的计算机少年的梦幻生活。少年黑客看到了软件业下面深埋的黄金。但金钱的回报绝不是唯一的诱惑:编写软件是一场公平的游戏,逻辑的清晰与思想的锋利,决定着谁是游戏的胜方。这种游戏对于两个天才少年有着无与伦比的吸引力。
对这两个少年黑客来说,这是一段令人难忘的经历。盖茨说:"计算机鼓舞我们沉浸在一种梦想中,总有一天上百万的人都会拥有他们自己的计算机。每过一年,我便越加坚信计算机和计算机的使用必定会变得越来越廉价和普及。我敢肯定我如此坚决地去帮助开发个人计算机的原因之一就是我自己想要拥有一台。"
盖茨上了哈佛大学,艾伦则在波士顿找了一份程序设计工作。他常常开车到哈佛,以便与盖茨继续关于未来计划的长谈。最终,他劝说盖茨出来创办一家软件公司,从而使盖茨成为哈佛大学最著名的辍学生。两人1975年树起了微软的大旗,为第一台个人计算机编写不同版本的BASIC语言。
两人形成了一种极其亲密的关系:盖茨是一位从不松懈的软件写手和竞争者,而艾伦则是一个目光远大的梦想家。在多年的合作中,他们还争吵过多次,最终,一场大病后艾伦离开了微软,成为美国最大的高技术风险投资家之一,与盖茨变得疏远起来。盖茨费了很大的劲修补两人的关系,成功地劝说艾伦回心转意,出任微软的董事。"我们喜欢在一起谈论我们儿时的梦想是怎样成真的,"盖茨说。"在1997年的《福布斯》亿万富翁排行榜上,保罗·艾伦名列第6,财产达141亿美元。现在,在湖畔中学他们的老教学楼对面,矗立起了一座现代化的艾伦。"盖茨科学中心(在为中心命名时,盖茨掷硬币输给了艾伦)。
◇微软的数学夏令营
40岁的史蒂夫·帕尔默(Steve Ballmer)在微软的会议室里跳来跳去,就像他在哈佛大学担任足球队长时一样。"比尔在哈佛时和我住同一间宿舍,"帕尔默说。"他玩扑克一直玩到早晨6点,我会在早餐时遇见他,一起讨论应用数学。"他俩在一起修研究生水平的数学和经济学课程,但盖茨故意制定一套行事策略:大多数的课程都逃课,到期末的时候再玩命学以应付考试。"我想看看我花尽可能少的时间能够得到多高的分数。这是一种游戏——不过是一种老把戏而已。"按照帕尔默的说法,盖茨是他所遇到过的最聪明的人。
帕尔默和盖茨过着很不相同的生活,但他们都竭力想把上课时间降至最少,同时又能得到高分。社会活动占据了帕尔默大量的时间,他不仅管理足球队,担任校报广告经理和一个文学杂志社的社长,还加入了一个社交俱乐部哈佛兄弟会。在他的影响下,盖茨参加了更多的社交活动。
1980年,当微软的生意不断发展时,盖茨需要一位能干的非技术人员帮助管理公司,他想到了老伙伴帕尔默。帕尔默毕业后,曾在宝洁公司任产品经理,几年之后,他决定去上斯坦福商学院。当他接到盖茨的电话时,才学了一学年,并打算拿到学位,但当盖茨把微软的产权给他一部分的时候,他也成了一个无限期休假的大学生。(他的选择被证明是对的:帕尔默成为微软制造的第三位《福布斯》上榜富翁,财产75亿美元,名列第27)。
帕尔默到达微软后不久,和盖茨就发生了激烈地争吵,原因是帕尔默认为公司需要立即雇用更多的人,而盖茨则声称这会使他破产。盖茨有一个规矩:微软不能举债,即使在没有什么收入的情况下也必须在银行里存上足够的能保持一年运营的钱(他现在拥有90亿美元现金而没有任何长期债务)。两人各不相让,最后还是老盖茨出面打圆场。
"冲突是一件好事,比尔把这种意识带进公司来,"帕尔默说。"微软与宝洁存在着惊人的差别。在宝洁,人人都彬彬有礼,而比尔清楚,如果你顾忌太多会妨碍深入到事情的核心。他喜欢任何人、甚至一名低级雇员对他提出质疑,当下属反抗的时候,会更加赢得他的尊敬。"在微软,这被称作一种"数学夏令营"心态:许多傲慢而聪明的家伙互相大喊大叫,认为所有的问题都像是数学问题,都有一个正确的答案。盖茨最喜欢说的一句话是:"这是我所听到过的最愚蠢的事情。"下属们都以得到盖茨的这句评语为荣。
这种纷争的气氛能够带来灵活性。当Internet的开放标准改变了游戏规则时,微软起初被弄得措手不及。公司内部争吵不休。很快,事情就变得很明显:该尝试一种新的战略了。盖茨仅用了一年的时间就使公司发生了转向,粉碎了人们关于"一场革命的先行者会被下一场革命所淘汰"的说法。
◇什么事情使他夜里睡不着?
盖茨喜欢开着高速轿车风驰电掣地上路。微软刚创业时,设在新墨西哥州的阿尔伯克基,他买了一辆保时捷911,常常驾车在沙漠中飞奔;他曾因半夜在街上疾驶而入狱,靠艾伦把他保出来;微软搬到西雅图后,他3次因超速而被警察撕了罚单,有两次是在同一条街上被同一位警察抓住的。后来,他又买了一辆保时捷930,称之为"火箭",接着是一辆奔驰,一辆美洲豹XJ6,一部38万美元的保时捷959,不过这辆车由于不符合进口车的排放标准而被扣压在海关。盖茨于是买了一辆法拉利345,开着它到处兜风。
尽管有这些记录,盖茨从来不系安全带。他谈话时很少看你,这令人窘迫,但他在驾车时却会看你,这使你倍感惊慌。一个雨夜,他带记者去参观他正在建造中的家。盖茨的"未来之屋"开工4年之久,1997年下半年完工。新居在华盛顿湖畔依山而建,占地3700平方米,据称耗资达4000万美元。伸向夜空的是三个相连的玻璃亭,用旧的经过加工的冷杉大柱支起来,看上去有点像乔装的大公司会议中心。山脚建有一座能停放30辆轿车的停车库。
盖茨描述说:"当你走进房子时,所遇到的第一件事是有一根电子别针夹住你的衣服,这根别针把你同房子里的各种电子服务接通。凭你戴的别针,房子会知道你是谁,你在哪儿,房子将利用这一信息尽量满足甚至预见你的需求。当外面变暗时,电子别针会发出一个移动光带,陪你走完这幢房子,同时有音乐相伴。空房子不用照明,当你沿大厅的路往前走时,你可能不会注意到你前面的光渐渐变得很强,而身后的光正在消失。音乐也会和你一起移动。尽管听上去音乐无所不在,但事实上,房子里的其他人会听到完全不同的音乐,或者什么也听不到。电影或新闻也能跟着你在房子里移动。如果你接到一个电话,只有离你最近的话机才会响。"像盖茨本人一样,这所房子很迷人,很有趣,但也有点令人害怕。
盖茨在结婚前就打算建这座房子,最初它被设计成单身汉小屋,但当梅琳达和他结婚时盖茨改变了计划,把它变得更适合一家人住。10年前,微软公司在曼哈顿举行新闻发布会时,盖茨与梅琳达相遇。那时她为微软工作,后来成了互动式内容部门的负责人。她们的女儿詹妮芙于1996年4月出生。梅琳达现已离开了微软公司,她热心于慈善事业,担任了杜克大学的董事。她曾在这所学校修计算机学本科和商学研究生课程,和盖茨一样,她极其聪明,有很强的独立性,并且具备类似盖茨母亲的社交才能,喜欢组织各类活动。但她对自己的私生活守口如瓶,从不接受记者采访。
"过去我常常想,女儿到两三岁会说话时,我才会对她感兴趣,"盖茨说,"但我现在对女儿已很投入。她刚会说'爸——爸',有了自己的个性。"盖茨在一次销售会议上拿出詹妮芙的照片给大伙看,打趣说,现在除了Netscape以外,还有另外的事情使他夜里睡不着觉。
◇亿万富翁俱乐部
微软很久以来就以智商和"智力带宽"为标准来雇用员工,盖茨是无可争议的榜样。公司中流传的一种说法是,和大多数人谈话就像从喷泉中饮水,而和盖茨谈话却像从救火的水龙头中饮水。盖茨和他的副手们都认为宁可找一些未受过训练但非常聪明的年轻人——他们把这叫做"克隆比尔"——也不找那些经验过于丰富的人。招聘过程不仅仅检验申请人的知识,而更多地是考察他们处理复杂问题的能力。
盖茨的聪明才智主要体现在他所称的"钻探"能力上。一次在参观时代公司(TimeInc.)的新媒介装备时,他飞快地回答了一群编辑提出的问题,似乎事先背好了答案;但准备出去的时候,他提出看看互联网络服务器,用45分钟向那里的技术人员提出尖锐的问题,使他们受了一场折磨。他对泛泛而谈兴趣索然,对其他人也没有半点好奇之心。当一些人试图靠闲聊与他建立私人亲密关系时,他顿感乏味。甚至和他在一起呆了很长时间以后,他对你的所思所想已知之不少,但对你居住何处、是否成家一类事情却一无所知。他根本不关心这些。
《时代》周刊的记者说,在这方面,克林顿正好与他形成对照。两人同是生育高峰时期出生的人,盖茨分析问题逻辑严密,感情深藏不露;克林顿同样聪明,但缺乏智力训练,随时乐于与人建立亲善关系。一次他们一起打高尔夫球,总统一如往常,努力保持个人的魅力,试图建立情感上的纽带关系。他对盖茨母亲的去世表示哀悼,他的母亲也刚刚去世,两人同病相怜。他还温文有礼地教梅琳达打高尔夫。但盖茨注意到,克林顿对技术问题没有丝毫好奇心。
沃伦·巴菲特(Warren Buffett),世界闻名的股票交易大师,几年来一直与盖茨在富翁排行榜上争夺冠亚军的位置。他现在已经无可置疑地失败了,在《福布斯》的名单上以232亿美元的财富名列第三。他对盖茨的智力惊叹不已。"他喜欢那些需要解决问题的游戏。我曾经教他玩一种4个骰子的游戏,骰子上的数字以一种复杂的形式排列,平均每一个都能吃掉另一个。在我教过的人中只有3人看出了其中的门道,发现要想赢就得让我先选我要掷哪一个骰子。盖茨是其中之一。"
从表面上看,巴菲特似乎不大可能与盖茨结为好友。这位66岁性格奔放的理财家已经当上了祖父,只是在最近才开始学习使用计算机。盖茨说:"多年来我一直尽力琢磨如何才能诱惑巴菲特使用个人计算机,甚至提出退位让他来干。他并不感兴趣,后来之所以改变了态度,是因为有一天他发现可以用联机服务与全国的朋友玩桥牌。最初的6个月,他回家后连续玩几个小时。尽管他还竭力躲开技术和技术投资问题,可他一旦试用计算机,就着迷了。"盖茨和巴菲特一项共同的爱好是打桥牌。一次,盖茨带着梅琳达和他们的女儿飞往旧金山去探望巴菲特夫妇,结果是下了飞机以后他们一口气打了9个小时的桥牌。
两人喜欢一起出去度假。巴菲特最喜欢讲的故事就是,1995年,盖茨和梅琳达组织了7对夫妇前往中国游览。"我们有一段时光是在长江上的一艘游艇中度过的。这艘游艇共有5层,通常情况下要载上百人,"巴菲特说这话的时候,仿佛一个孩子在描述迪斯尼世界的神奇。"每天晚上梅琳达都安排不同的活动。"他们在舞厅里唱卡拉OK,并表演莎士比亚戏剧的片段,"还有一些小把戏,如猜测我们吃了多少顿饭,猜中者由梅琳达和比尔发奖。"巴菲特说,在放松的时候,盖茨很有幽默感。
盖茨和巴菲特的友谊与生意无关。巴菲特从不投资技术股,第一次遇见盖茨时,出于好奇,他购买了100股微软股票("我再多买一点就好了,"巴菲特大笑说)。盖茨则称他对巴菲特公司的投资"只有"1000万美元("我真希望能多投一点,"盖茨也开玩笑说)。但盖茨同巴菲特一样都对媒体感兴趣,喜欢打趣说他已生产出了一部叫做Encarta的电子百科全书,它的销量已超出了由巴菲特控制的《世界图书百科全书》(World Book)。但一些媒介股票的价格与微软相比很便宜,基于这一点,盖茨也许会采取大的兼并活动(在特纳通信公司与时代——华纳公司合并之前,盖茨曾经很认真地考虑过花20亿美元投资CNN的可能性)。如果是这样的话,巴菲特会是一个有用的伙伴。
◇商业竞争是一场流血的体育比赛
盖茨办公室里的电话几乎从未响过,微软公司的"校园式"总部的电话铃声好像也不太多。盖茨管理公司主要通过三种方式:他每天(和每夜)发出100多份电子邮件,常常一边发信一边自觉有趣而窃笑;他差不多每月与高层经理开一次会;而最重要的是,他每天召开一两次小型总结会,与会人员都是公司开发各种产品的骨干,他估计这占据了他70%的时间。
盖茨从来不直呼下属的名字,既不赞扬也不安慰他们。但他一字不漏地听,而且很民主。在和WebDVD小组的人员交谈时,即使他不同意人们对DVD功能的分析,他也克制了自己出名的脾气。他说"请指教",过了一两分钟,他就中断谈话,要求"把技术细节的报告送给我"。虽然DVD不是微软的核心业务,盖茨也希望在这一领域获胜。WebDVD小组的任务是为电视机提供一张装有Web浏览器和其他内容的DVD盘,小组成员认为,每张10块钱的版税过低。"为什么要标更高的价?"盖茨问。下属解释说,从他们放进盘里的东西来看,10块钱的版税很难赚到钱。盖茨的脸色严肃起来。他们没有看清楚整个画面。"我们的战略目标是使Windows CE(微软推出的用以操纵手持计算机设备的操作系统)标准尽可能普及到每个地方。在今后几年里我们可以不赚钱。我们第一次推出MS-DOS的时候也不曾赚钱。如果靠10块钱就能打开市场,那么就去做吧。"
这就是比尔·盖茨的目标。对人们提出的微软公司在台式计算机领域能够取得多大限度的发展这一问题,盖茨针锋相对的回答是:编制可在更多种类的计算机上使用的软件,这些计算机将用在住宅、汽车甚至钱包中。你能够在微软公司存取钱款,在微软公司预约旅游,从微软公司购买音乐制品,在微软公司读书评,在微软公司的频道上看有线电视。人们也许会发现自己在工作、购物和娱乐时常常要和微软公司打交道。最终,一种以视窗为基础的家庭控制系统也许甚至会关闭卧室中的电灯。一位风险投资家迈克尔·莫里茨说:"像微软公司这样能够在20世纪末影响人们生活的诸多方面的公司,在世界历史上很少见。也许你得追溯到罗马帝国时代,才能找出具有微软公司目前这种影响的组织。"
他母亲也许习惯了盖茨争强好胜的性格,但计算机业的很多人却不买他的账。环球网上有一些专门谩骂盖茨的站点,一些律师事务所专门找他的麻烦,Netscape、Oracle和Sun公司公开宣称,要针对他"主宰世界的计划"进行一次神圣的十字军东征。对盖茨的指责不仅仅是因为他的成功,而是由于他试图不公正地、也许是非法地运用微软在桌面操作系统上的垄断优势,进一步控制从文字处理到电子数据表、从环球网浏览器到内容的一切领域。微软正把它的Internet Explorer浏览器以及Microsoft Network内容集成到视窗操作系统中。
"他们试图利用现有的垄断阻碍新技术的引进,"代表Netscape和其他微软对手提出反托拉斯诉讼的律师加里·里贝克说。盖茨并不想道歉:"任何没有浏览器的操作系统都将完蛋,那么,我们是应该改进产品呢,还是彻底完蛋?客户会因此而受益,就像他们曾经从图形界面,多任务处理,数据压缩和其他技术中获益一样。"
除了法律诉讼以外,对手们提出了一个更加具有哲学意义的话题:盖茨不择手段的竞争方式是否损害了个人计算机早期发展中形成的合作式的黑客准则?罗伯·格雷瑟曾在微软担任过经理,他说,起初自己很钦佩盖茨的远见,"但盖茨太无情,他是物竞天择适者生存的达尔文主义者。他寻求的不是双赢,而是想方设法让别人失败。在他的眼里,成功的定义是消灭竞争,而不是创造杰出。"
这与盖茨在6年级时他的心理医生所下的结论异曲同工。格雷瑟说:"比尔仍旧把自己当作一个孩子,刚刚创立一家公司,唯恐如果让别人放手竞争的话自己就会被挤出场外。"电脑业有影响的通讯刊物价《1.0》的发行人兼主编爱瑟·戴森是盖茨的老友,对他充满赞赏的同时,也不乏疑虑:"就社会责任与人际关系而言,他从未真正长大成人。他非常聪明,但行事却像个孩子。他可能是一个有趣的伙伴,但他也可能冷酷无情。"
"如果我们不是冷酷无情的话,我们能生产出更具创新性的软件吗?我们宁愿消灭竞争对手而不是培育市场?!这是彻头彻尾的谎言,"盖茨冷冷地说。"是谁培育了这个市场?是我们。是谁经受住了比我们规模大10倍的公司如IBM的攻击?"他指着Oracle、sun、Lotus、Netscap等竞争对手的名字说,"他们的竞争性一点也不比我们逊色。我们获胜是因为我们雇用了最聪明的人。我们根据用户的反馈不断改进自己的产品,直到它们尽善尽美为止。每年我们都举行研习会,思考世界往哪个方向发展。"他对外界所说的微软总是窃取对手的构想——例如Apple 的图形界面和Netscape的浏览器——而不是开辟自己的道路的说法嗤之以鼻。"图形界面是由施乐首先开发出来的,而不是Apple。我们很早就在这上面下工夫,所以Microsoft office应用程序才会成为最好的。"
盖茨喜欢这一切。智力挑战是乐趣。运动是乐趣。猜谜是乐趣。而与聪明的人一起工作则是超级乐趣。其他人也许认为他冷酷无情甚至残忍;但对他而言,商业竞争就像体育比赛,或许是一场流血的体育比赛。
◇战略大转变
互联网络的兴起,预示着新时代的来临,过去20年间,微软赢得个人电脑的世纪,在新竞争时代,盖茨又将如何领导微软赢取下一场战争?
1996年,盖茨在短短的6个月时间改变公司战略,迅速抢占网络大饼,对于资产达到80亿美元,员工达到2万人的微软来说,盖茨对公司的战略来了个180度大转弯是极少有经理人员敢尝试的。正如梦幻工厂(Dreamworks SKG)的负责人之一杰弗里·凯岑伯格说:"我真想不出还有哪家公司取得过如此成就而又能在20年后停下来作出决定彻底改造自己。他们所正在从事着的是决定性的、迅速的和令人惊奇的。"
盖茨使微软成功转型是他获得《商业周刊》1996年度全球25位最佳管理者的主因,《商业周刊》也披露了微软转变的内幕,这是一个充满着曲折、转机、失误,甚至还包括关键时刻生病在内的故事。
噢,未来网络之光已清晰可见,
市场份额扩大,目前终将实现。
不久微软测览器将随处可见,你不再被认为无所作为,
我们接纳,我们扩展!
微软无名氏作于公司内部刊物《微软新闻》
这是在1996年5月中旬星期五晚上的6点30分,微软花草繁茂的公司大院仿佛就是莫奈笔下的油画——艳紫色、青粉色的花朵点缀其间,好一派盎然春意。然而,好像没有人留意于此。走进有800名员工的工具软件部——该部专门生产用于协助软件开发者制作新软件的软件产品,你会发现有几乎一半的程序员仍伏案计算机旁,而他们中的许多人今天已工作了13个小时。空空如也的咖啡杯、门后挂着的睡袋清楚地表明夜就要来临。明天还会是这样,后天也仍会如此。也许直到明年仍将如此。
业已无坚不摧、堪称中流砥柱的微软公司进入的是一个全新的天地——人称"互联网络时代":节奏如此之狂热,就仿佛是在三伏天似的——一年的事就抵得上以往7年之多。微软公司的员工们通宵达旦地工作着,希望把公司落后于网景公司(NetscapeCommunications Corp)、太阳微系统公司(Sun Micosys tems Inc)等这样一些对互联网络志在必得的公司的宝贵时间补回来。微软公司互联网络工具产品经理科尼利厄斯·威利斯说:"好吧,我们是错过了互联网络的首轮较量。不过,我们现在已开始行动了!"
事实上,直至6个月前,微软公司看上去还好像会在电脑空间的角逐中失利。微软公司远远落后于那些互联网络的新贵们——靠互联网络崛起的新公司,这不由得让业内分析家们担心,以软件产品统治了整个个人电脑时代的微软公司在互联网络计算机新时代里究竟是否会被淘汰出局。
要想看看微软公司到底是怎样对警告信号视而不见的并不困难。早在90年代初,当互联网络奇迹般地由一个无足轻重的个人网络一变而成为全球性的通信与计算机媒介之时,微软公司增长正旺。销售额增长了两倍,达到38亿美元。在职员工也由1990年的5600人增至1993年的14400人。所有这些都要归功于视窗软件的成功。
时至1993年,技术方面的消息灵通人士发现了所谓的"环球网"(World WideWeb)。它可以让你在网络上显示图表和照片。尤为重要的是,你只需在某一个以高亮方式显示的单词上轻轻一点,环球网就可以让你在网络计算机间跳来跳去。然而,对于微软设在华盛顿州雷德蒙德的公司总部而言,环球网不过是个新鲜玩艺儿罢了。微软公司的董事长比尔·盖茨说:"我是不会说'现在已清晰可见环球网将在今后几年里迅速发展'之类的话的。如果当时你们问我是否大多数电视广告将会在内容中加入环球网地址(URL),我会放声大笑。"就算盖茨及其经理们对环球网未来的发展轨迹略知一二,他们也有更紧迫的事要考虑。政府的决策者们对微软公司被指控所犯的反竞争行为的调查正进行到一半。一个秘密小组正在创建一个服务项目以同美国在线公司(AmericanOnline Inc.)相抗衡。再有,就是要制作信息高速公路精品——交互式电视视频服务器、电视机顶置盒的程序等等。尤为重要的是,众多的程序员们正齐集一堂,为完成后来的95视窗而忙碌着。
微软公司对环球网所作出的公开反应一直沉默不语。直至1995年秋,环球网的发展势头之猛已让人无法忽视——它已构成了对微软公司的威胁,已有约2000万人不用微软公司的软件而在网络上驰骋。更糟的是,在太阳微系统公司所开发的编程语言Java的推动下,环球网作为一种新式"平台"正在崛起,对视窗在个人电脑上的霸权地位构成了挑战。
盖茨坐不住了。1995年12月7日,他为分析家、记者和客户们安排了一次全天性活动,旨在说明微软公司打算全面参与并赢得这场新的软件大战。微软公司将生产网络浏览器、网络服务器,并对微软公司现有的程序进行网络化。微软公司甚至还将不计代价地获得太阳公司Java语言的许可证。
从那时起,雷德蒙德的每个人都进入了互联网络时代。在这个有着35座建筑的大院的每个角落都进行着网络项目的开发工作。1996年2月份成立的"互联网络平台与工具部"的员工人数增加到了2500人——比网景公司以及紧随其后的五大网络新贵的员工人数之和还要多。一份由迈克尔·金斯利编辑的名为《石板》的颇具特色的网络杂志,继1996年6月24日在MSNBC上首次亮相之后,于1996年7月15日正式创刊。MSNBC是一个由微软公司与美国全国广播公司(NBC Inc)联合创办的有线新闻频道和网络地址。到1996年秋,微软网络也将以巨型网络地址的面目重新出现。盖茨说:"当前,互联网络对我们来说最为重要。它将带动一切。我们的软件个个都是核心产品。"
尽管由这些产品所带来的影响力我们还要拭目以待,微软公司攻势之迅速、火力之密集却已经改变了竞争对手和分析家们的推算。市场调研公司——加特纳集团公司(Gartner Group Inc.)的副总裁斯科特·温克勒说:"人们要问的已不再是微软公司是否会被互联网络置于死地,而是微软公司是否会称霸互联网络。"
盖茨,这位当年热衷于商业史的学生,十分清楚其他主宰市场的大公司,如通用汽车、IBM之类如何由于其高层经理人员未能洞察到业内所发生的根本性变化而栽了跟头。解决这个问题成了盖茨1995年秋出版的畅销书《未来之路》中的一个突出论题。他说:"我还没见到有这样的情况——一个领导者能把全部的精力和注意力集中到那些他根本没抓到手的新机遇上。"
对微软进行网络化的工作开始于1994年2月。当时,盖茨的技术助理史蒂文·斯诺夫斯基在为公司招聘人才的途中,回到母校——康奈尔大学。被大雪困在纽约州伊萨卡机场的他回到了康奈尔校园。在那里,他所看到的情景是:学生们在教室之间穿梭往来、向终端键入指令、从网络上接收电子邮件和课程表。
互联网络传播起来就像扑不灭的野火一般。它不再是一个专业技术性质的网络,像7年前斯诺夫斯基在校时那样,而是一个学生和教职员工都在使用的、用以同校内乃至全世界的同事进行交流的工具。他马不停蹄地给盖茨及其技术人员发去了一份电子邮件,写道:"康奈尔联网了!"
盖茨的一名下属给斯诺夫斯基的回复是:已经有过搞网络的人"在拿同样的内容烦我们。也许你们该碰碰头。"那个人就是阿拉德。1991年受聘之时,这位一脸稚气的程序员对微软公司是否"了解互联网络"很担心。不管怎样,他还是签了约。这表明他有能力帮助公司去了解互联网络。1992年时,阿拉德是微软公司唯一一位在自己名片上写着"互联网络技术程序经理"的程序员。他回忆说:"那时我势单力薄。"
阿拉德的工作是为微软公司的LAN管理器和Windows for Workgroups软件建立TCP。"IP——一种网络通信格式。长期以来,TCP。"IP一直是在太阳微系统公司等所生产的Unix型电脑上使用的标准。阿拉德说,但是对于微软公司而言,按执行副总裁史蒂文·帕尔默的说法,TCP-IP只不过是个"复选项"。阿拉德还记得帕尔默说过:"我不知道它是什么。我不想知道它是什么。我的客户们对之表示强烈不满。别再提那伤心事吧。"
在1993年早些时候的一个不受支持的项目中,阿拉德负责监管微软公司第一个互联网络服务器的开发工作。这是一种可将微软网络地址同互联网络上的其他地址进行连接的计算机。该项目计划向客户们发送测试性的TCP-IP代码文件。不久,他们又公布了其他一些弥补缺陷的措施,使该服务器成为互联网络上使用最多的10种服务器之一。
然而,这几乎没有引起高级管理层多少关注。当时37岁的盖茨和他的助手们根本没有像公司里许多新一代、二十几岁的年轻人们那样看到互联网络的作用。加之许多关于改写视窗软件的烦心事,使得盖茨他们几乎没有时间搞新的项目。
阿拉德愈加感到失望。有了"马赛克"(Mosaic),互联网络沸腾了。"马赛克"是一个由伊利诺斯大学一名性格早熟的计算机系学生编写并在互联网络上发布、可供任何人卸载的浏览器程序。突然间,环球网上多了这样一种使用便捷、面向公众的点击式浏览器。1994年1月25日,阿拉德起草了一份题为《视窗:互联网络下一个令人心动的应用软件》的请战备忘录。
阿拉德建议建立一种"马赛克"式的浏览器并在"芝加哥"中使用TCP-IP。"芝加哥"是日后成为95视窗软件的代号。该备忘录里还使用了不到两年后就成为微软公司战斗口号的语言:"接纳"互联网络标准,"扩展"视窗入互联网。阿拉德说:"最后,我着实不能再忍受下去了。我感到公司就是理解不了。"
斯诺夫斯基一参与进来,情况就开始有了转机。两人开始交换看法。斯诺夫斯基很快就迷上了网络。斯诺夫斯基说:"我把人们拖到我办公室来。起初他们大声地抱怨。我能让他们对这东西感到兴奋不已。"受其感染的人里,盖茨就是一位。盖茨说:"当斯诺夫斯基开始谈及他在康奈尔看到的现象,向我展示了'黄鼠'网络以及环球网上早期的一些东西时,引起了我的注意。我觉得'这东西蛮不错的'。"
老板批准召集一次经理静思会议,讨论一下互联网络的事。这是关键性的突破:在微软公司,只有当盖茨感觉到经理们需要将注意力集中到某个关键问题上时,才会召集这种会议。1994年4月5日,正值斯诺夫斯基康奈尔之行两个月后,微软公司的头面人物齐集位于华盛顿州柯尔克兰附近的沙威大厦——一座建于1909年、用于召开会议的建筑。盖茨及其各部门的头脑们认真研读了斯诺夫斯基编写的长达300页的互联网络情况简介。会议的议题是:互联网络的重要性以及微软公司对互联网络的投入问题。
在一个突破组里,阿拉德同拉塞尔·西格尔曼争论了起来。那时,西格尔曼正负责"奇迹"(Marvel)的开发工作。"奇迹"就是现在微软网络联机服务当时的代号。阿拉德认为"奇迹"不应渲染微软专有色彩,而应以网络标准作为基础。但西格尔曼坚持自己的观点。在这场争论中,西格尔曼获胜了。后来,为改正这一错误抉择所付出的代价高达上百万美元。
网络工作还是取得了进展:TCP-IP将被加进95视窗和视窗NT中。视窗NT是能在网络服务器电脑上运行的视窗版本。销售组被要求使用环球网来分发营销信息。应用软件组同意给字处理软件WoId配备生成网络页面的功能。
此后,盖茨对网络发展的参与又进了一步。他把"四月思考周"(半年一次的静思)的大量时间用到了对互联网络的思考上。在盖茨1994年4月16日的备忘录中,他说:"互联网络战略与互联网络技术目标"是公司发展的首要标志。盖茨写道:"我们希望并将投入人力物力,成为'支持互联网络'运动的领导者。"
尽管步子不大,但这是第一步。阿拉德说:"我还不认为他已知道该下多大的赌注。"然而,董事会成员戴维·马考特却认为他已经知道了。他回忆说他感到很"惊奇",微软公司在互联网络上投入的是如此之少。加利福尼亚州门罗公园的技术企业投资者公司(Technology Venture Investors)的一位主要股东马考特说:"他们不在硅谷。要是在这儿,你会感到网络就在你身边。"他在1994年4月的董事会上提出了这一问题。盖茨的反应怎样呢?马考特说:"他认为互联网络是免费的。那里没有钱赚。互联网络生意怎么会有意思呢?"
对于地位日显重要的一伙竞争对手们来说,显而易见,那里存在着巨大的机遇。如果微软公司不去抓住它,它们就能够动摇这一软件巨人的统治地位。太阳公司、网景公司、甲骨文公司(Oracle Corp.)、IBM公司以及其他一些公司都认识到,互联网络是重排座次的好机会。
犹如细胞一般不断激增的网络新贵们也有同感。利考斯公司(Lycos)、信息搜索公司(InfoSeek)、点掷公司(PointCast)等几十家公司杀人本应有微软一份的真空地带。这些公司中最具特色的一家是由辞去其亲手所建的硅图像公司(SiliconGraphics Inc.)董事长职位并抓住互联网络机遇的詹姆斯·克拉克领导的。他手上有能下金蛋的金鹅:那个伊利诺斯大学23岁的程序员马克·安德利森。网景通信公司(Netscape Communications原马赛克通信公司)成立于1994年4月4日,正值"沙威静思会议"前夕,到1994年10月,互联网络上各处都在卸载该公司的"导航员"浏览器软件(Navigator)。
1994年春,互联网络火爆起来。上百万个人电脑用户登记上网,商业性网络地址从1991年的9000个增至约21700个。甚至IBM公司也收到了董事长小路易斯·格斯特纳发自家中的问候。通用电气公司(General Electric)、塔珀器皿公司(Tupper ware)、沃尔沃公司(Volvo)以及海厄特宾馆(Hyatt Hotel)也出现了类似情况。时代-沃纳公司(Time Warner)使用的"路径探寻器"(Pathfinder)成为其电子版杂志的一大特色。人们日益感到是互联网络——而不是交互电视——正成为通向信息高速公路的必由之路。太阳公司正是抓住了这一点,开始将一种用于交互电视的软件语言改写为日后的Java语言。
1994年4月,在康岱(Comdex)春季交易展中,斯诺夫斯基见到了Booklink——CMG信息服务公司的一种浏览器。他把BookLink给当时任微软公司95视窗业务负责人的布拉德·西尔沃伯格看了。经理们开始就给该项技术发放许可证一事进行谈判。然而,就在谈判缓慢进行之时,美国联机公司突然闯入,于11月份以3000万美元的价格买走了BookLink。西尔沃伯格说:"这使我们觉醒了。我们必须更加积极进取,更加充满活力才行。在这个新的天地里,可谓天上一日,地下十年。"
在此期间,盖茨正在为身处新兴的网络化世界中的微软精心绘制新的公司战略。然而,正如他在1994年10月份的备忘录中所描述的,这是一次"巨变"。方法就是要利用微软现有的产品。其他的微软人也都确信互联网络是发展方向。
其中之一就是本杰明·斯利夫加。他现年35岁,是微软公司的浏览器软件——互联网络探索者(Internet Explorer)的项目负责人。1994年年中,他和其他3名程序员正在研究筹划95视窗的后继产品所应具备的特色。他进入互联网络并很快找到了答案:1994年8月15日,他给小组成员们发了一份电子邮件,说他们所需要的正是浏览器,而且甚至可以给95视窗准备一个。当网景公司的"导航员"1994年秋上网之时,斯利夫加对其研究了一番。而后,他找来6个人,一起筹划95视窗的浏览器特色。
为了加速工作进度,他手下一名程序员到伊利诺斯州纳波维尔的小型望远镜公司(Spyglass Inc.)进行了一次采购旅行。该公司是网景公司的竞争对手。对于小型望远镜公司的首席执行官道格拉斯·考贝斯而言,这真是一个颇具讽刺意味的时刻。6个月前,他前去拜访微软公司,得到的却只是断然回绝。考贝斯说:"不出所料,他们讲'我们自己会做的。'"可是,到了1994年下半年,网景公司开始不断发展。这时,微软公司开始急于成交了。1994年12月16日,微软公司在小型望远镜公司的许可证上签了字。
尽管如此,进入1995年后,微软公司的管理层仍将注意力集中在"芝加哥"上。该软件计划于1994年12月推出,后推迟到1995年年中。最终,于1995年8月份以95视窗的面目上市了。另外,微软公司还忙着要完成针对公司市场的视窗NT软件。盖茨说:"这些都是重点。而互联网络不过像是远方传来的隆隆声。"
盖茨还指示,微软网络应与"芝加哥"同时面世。微软网络的经历中充满着"本应更好"式的遗憾。1992年12月,当西格尔曼开始计划时,互联网络还不算特别引人注目。当时真正的明星是美国联机服务——一种基于窗口方式的联机服务。接受该项服务的成员正在迅速增加。于是,盖茨在1993年5月批准了西格尔曼的计划。该计划将开设一项可与美国联机相竞争的服务。这项服务的一大优势就在于使用该项服务所需的软件将包括在95视窗中。
1993年秋,微软网络小组奋力争取及时完成微软网络以实现与"芝加哥"同时面世的目标。然而,盖茨已注意到互联网络正在隆隆作响。他同意让长期担任微软公司经理、曾倡导微软公司闯入多媒体领域的罗布·格拉泽就互联网络对微软网络的影响问题进行一次分析。格拉泽的结论是:微软公司应当从根本上改变其战略,让联机服务成为互联网络的组成部分。
这时,厄运袭来。1993年11月,时年34岁的西格尔曼脑部出血。尽管他身体将能恢复,但他的缺席使得平素对工作要求严格的格拉泽不得不有所放松。格拉泽向西格尔曼的手下展示了自己的计划。但头儿不在,微软网络小组已经是在超负荷工作了,格拉泽就没给他们再加压。以前曾是微软网络小组成员的杰弗里·利勒说:"我们实在无法花费大量精力去改变我们的计划。"格拉泽也说:"我感觉命运在同微软作对,不让微软公司早些真正了解互联网络。"
不管怎么说,微软网络还是个蛮有特色的项目。1994年11月份,盖茨在康岱发表的一次重要讲话里披露了微软网络计划中的服务项目。在短短几周时间里,他就说服了电信公司(Tele- Communications Inc.)出资1.25亿美元购买微软网络20%的股份。电信公司负责人约翰·马隆差点儿就把这笔钱投给微软公司的竞争对手美国在线公司。不过,正如美国在线公司的首席执行官史蒂文·凯斯所说:"盖茨在最后一刻说服或者说是恳求他不把钱投给美国在线公司。"三周之后,微软公司以1640万美元买下了UU网络技术公司(UUNet Technologies Inc)。现在,该公司负责办理微软网络业务。
微软网络尽管如此,盖茨还是在1995年5月发出了向互联网络进军的紧急动员令。他发表了题为《互联网络浪潮》的备忘录。其中他谈及的主题在硅谷中久久回荡。盖茨宣布互联网络是继IBM个人电脑之后"最重大的进展"。他写道:"我对互联网络重要性的认识先后经历了几个层次。现在,我要说互联网络是重中之重。"
1995年5月27日,斯利夫加发表了自己的紧急动员令。题为《环球网,下一个平台》。他警告说环球网具备取代视窗的潜力。斯利夫加说:"我不知道自己是否真的相信会发生这种事情。但我是想表明一种观点。"
微软公司的经理们日益感到互联网络的契机必须抓住——要在它溜到别人那儿去之前抓住。1995年6月1日,40位微软公司的经理聚在华盛顿州贝尔维尤的红狮旅馆,集体讨论互联网络战略问题。盖茨就"互联网络浪潮"发表了20分钟的讲话。斯利夫加原计划15分钟的讲话最后长达1个多小时。斯利夫加说:"我惹恼了一些人。"在一个关键问题上,斯利夫加建议微软公司像阿景公司那样,在互联网络上免费发送一些软件。斯利夫加回忆说:"盖茨称我是个共产主义者。"
经理们还逐个审阅了微软公司筹划中的每个互联网络项目,头一眼就看到了Java。反应如何?阿拉德说:"就像对我备忘录的最初反应一样,不冷不热。"
直到1995年8月份95视窗上市之后,微软公司才算真的全力投入到互联网络工作上来。盖茨说:"早在三四个月前,就已有迹象表明这东西的发展的确迅速。我说:'好吧,等我们的95视窗一上市,我就去好好思考一下它对我们战略的影响。我们能否制定这样一个战略?我们在互联网络上下赌,假设它真的会使人们对个人电脑和软件的需求荡然无存。要是真的那样的话,它又将如何改变我们的战略呢?'"
盖茨不能浪费丝毫的时间。1995年8月8日,网景公司成为众人注目的焦点。其引人注目的原始公开股票在发行第一天就从28美元涨到了58美元,使互联网络股票行市呈现牛市走向。公司股票上市后18个月,董事长克拉克便成为名义上的亿万富翁。而盖茨直到微软公司成立12周年的时候,才达到这一里程碑。
网景公司所赢得的远不只是华尔街的一批追随者。它在网络测览器方面取得了微软式的统治地位,获得了与那些在经营中一贯处于获利地位的客户们签约的机会。这些公司正使用网景公司的服务器程序建立其网络地址。与此同时,整个电脑王国因为太阳公司的Java软件而变得充满生气。这一软件使得通过互联网络改变程序或是网络页面成为可能。这一体系所导致的威胁在于有了它,视窗在环球网上的地位将变得无足轻重。1995年11月16日,由于互联网络的缘故,戈德曼·萨克斯公司(Goldman,Sacha &Co.)在其"推荐购买"表中去掉了微软公司股票。
这个教训很清楚:微软公司若要在网络计算机时代保住自己的位置,就必须参与互联网络的竞争,就必须遵守网络的规则,也就必须接受互联网络的标准——接纳它们、扩展它们,点缀上微软的装饰,努力保持微软的轴心地位。
微软公司转入互联网络时代。常爱言过其实的帕尔默则负责给这一转变打节拍。盖茨回忆道;"帕尔默说:'喂,我们进展到哪儿了?'我们说:'哦,我们有了不少的散件。它们本应该综合在一起。但现在它们还没有。'帕尔默说:'把它们综合起来,让它成个东西。实际上,只要选定个日子,你们到时候就能叫它综合起来。'"
日子已经定好了:负责平台项目的集团副总裁保罗·马里茨将于1995年12月7日召集一次精心准备的互联网络最高层会议。微软公司将宣布其浏览器计划、网络服务器计划、新的基于环球网的微软网络计划以及其他的行动计划。马里茨两个晚上都住在公司董事会的会议室,听取往来穿梭的经理们讲述他们的计划。微软公司一名经理理查德·童则启程前往各处,向互联网络顾问们求计。斯利夫加的小组就微软公司如何获取测览器30%的市场份额的问题写出了长达14页的备忘录。该备忘录建议让美国在线公司和电脑服务公司(CompuServe Inc.)给微软公司的浏览器发放许可证。
1995年12月6日晚8点,微软公司的高层经理们汇集在西雅图中心礼堂进行最后的彩排,他们仔细地将每项演示都过了一遍,盖茨甚至还对幻灯片上的文字细细推敲了一番。(与此同时,微软与太阳两家公司的经理们则在连夜就签署给Java发放许可证的协议一事忙碌着)直到午夜时分,一名公关部经理告诉盖茨说所有的演示都是压倒性的,之后整个展示会的准备工作才算一切就绪。他们还需要给记者们准备一个三点概括。已是疲惫不堪的盖茨躺倒在地。跟着,帕尔默也倒下了。人们都等待着,不晓得盖茨是在思考还是发火。最后,盖茨脱口说道:"我只是要让他们知道我们已经离不开互联网络了!"
从那时起,微软公司不再瞻前顾后。公司的员工们通过闭路电视系统收听互联网络的情况简介,通过电子邮件获取讲稿。随后,他们又收到录像带资料。盖茨要大家绝对清楚新的"前进命令"是什么。弗米尔产品部(Vermeer Product Unit)副总裁克里斯·彼得斯指出,盖茨大可不必为此担心。他说:"如果董事长发话说那样做就是成功,就会有一大批人那样做。"
如今微软公司已兴奋起来。马里茨说:"真正调动起我们积极性的是偏执狂和竞争。"当1995年12月8日,即微软公司引人注目之举过后的第二天,被问及来自微软公司的威胁一事时,网景公司的首席执行官詹姆斯·巴克斯戴尔打趣地答道:"上帝站在我们一边。"这话犹如是将火扔在干柴上一般。现任微软公司互联网络部负责人的西尔沃伯格说:"这种话是要把人都围在互相排斥的小圈圈里。我得谢谢网景公司。所有这些废话正好帮我们调动了积极性。"
微软公司所依靠的不仅仅是学术精神。据内部人士讲,在最高层会议期间,微软公司曾试图买下激励者公司(Excite)。该公司的"查询器"技术,和比它更为出名的竞争者的不相上下。该技术将帮助微软网络成为一条进入环球网其余部分有用的通道。内部人士说,微软公司的出价为7500万美元,但遭到激励者公司的拒绝。原因是,投资银行家们说如果激励者公司公开上市,获益会更多。1996年4月4日,激励者公司公开上市,目前价值为8400万美元。微软公司接下去的标购行动是以1.3亿美元左右的价格买下网络新贵——销售额不足的弗米尔技术公司(Vermeer Technologies Ine.)。这一标购获得了成功。现在,弗米尔公司颇受看重的"头版"软件(Front Page)正被用于生成网络页面。
1996年2月12日,微软公司向公众透露了其在与网景公司的竞争中所使用的一件重要武器——互联网络信息服务器(In ternet Information Server)。迄今为止,该软件免费卸载的数量已达到9万份左右。3月份,微软公司打了个漂亮的大胜仗:公司在网景公司的眼皮底下与美国在线公司好不容易达成了一项交易,使微软公司的"互联网络探索者"成为美国在线上主要的网络浏览器。作为交换,微软公司也作出了重大让步:在95视窗中加入美国在线,结束对微软网络的独家优势。微软公司正在从一个互联网络渴望者转变为互联网络夺冠者。英特尔公司的首席执行官安德鲁·格罗夫说:"这是商业务实态度的杰作。"
1996年6月,微软公司又将注意力转向内部网(in tranets)——一种建立在互联网络技术上的公司网络。6月13日,公司简略描述了其定于1996年夏季晚些时候发动的以视窗NT4.0版"头版"和一个新的查询软件。这对美林公司(Merrill Lynch &Co.)这样的机构来说是很有吸引力的。这类机构喜欢由一家公司为它们提供所有的常规软件和更新的互联网络应用软件。微软公司正为约2.5万台使用视窗的个人电脑和1200个网络服务器制作一种交易系统。该系统与内部网和互联网相连。
盖茨指望着像美林公司这样的客户能够在微软公司为互联网络在战略上填补漏洞的时候给予微软帮助和支持。举例来说,微软公司在合作软件与电子商业软件方面就仍然落在后面。
那些曾刺痛微软公司的网络新贵们说,微软公司所错过的远不是一点点。它们断言,雷德蒙德所发布的大都是空话。太阳微系统公司的首席执行官斯科特·麦克尼里轻蔑地说:"编个广告宣传是花不了很长时间的。"盖茨说微软公司将会推出自己所许诺过的产品。但他也不得不承认其工作尚未完成。盖茨说:"此刻,我们不能说我们已摆脱了险境。我们再有一年多的时间,一定会取得令人惊奇的结果。"
硅谷称盖茨为"软件业里的撒旦",word perfect公司前主管甚至称他为"带你过河,然后吃掉你的狐狸"。莲花软件(Lotus)创办人卡波尔说得比较中肯,"盖茨代表我们最好或最坏的一面。"但这些评论,丝毫无损于盖茨作为全球软件巨人的地位。
PostgresSql学习-Vacuum清理机制
什么是 Vacuum?
VACUUM — garbage-collect and optionally analyze a database
Vacuum 是垃圾回收机制,并能够对数据库进行分析(可选)。
在 PostgreSQL 中,Vacuum 机制是必不可少的,他能避免数据膨胀,解决事务ID环绕问题,并且能够提供分析统计信息供其它模块使用以便提升性能。
PostgreSQL 先行知识
Vacuum 会涉及到堆表的数据读取、索引和MVCC,此处简要介绍相关知识。
数据与索引的存储
在 PostgreSQL 中数据存储在堆表(table heap)中,与索引是分开存储的。
查询数据时,首先查询索引,找到记录后再到堆表中获取记录。
结合数据在磁盘上的存储,更具体的位置如下:
数据库所在位置
数据库以目录形式组织,路径为:PGDATA/base/oid,oid 可以从 pg_database 表查询得到。
postgres=# select oid, datname from pg_database; oid | datname------- ----------- 13395 | postgres 1 | template1 13394 | template0(3 rows)
表所在位置
表面以文件形式存储
postgres=# select pg_relation_filepath('foo'); pg_relation_filepath---------------------- base/13395/16384(1 row)
记录所在位置
记录存储在页(Page)中,每页一般 8K 大小。Item 指定了 Tuple 在页中的位置,Tuple 存储着具体的数据。
每条记录都有隐藏字段 ctid ,存储着记录所在位置
postgres=# select ctid, * from foo; ctid | id | content------- ---- ---------- (0,1) | 1 | dongdong(1 row)
本例中 ctid 值为(0,1)说明记录存储在 page_id = 0,item_id = 1,进而通过 item_id 可以获取到 Tuple 数据。
MVCC 多版本并发控制
MVCC 是针对事务读取的优化,简单地讲就是:对数据库的任何修改的提交都不会直接覆盖之前的数据,而是产生一个新的版本与老版本共存,使得读取时可以完全不加锁。当开启事务后,事务内数据相当于创建了一个“快照”。
PostgreSQL 中的事务由 32 位组成,顺序产生,依次递增,在当前会话中如果没有数据变更(如INSERT、UPDATE、DELETE等操作),事务ID保持不变。
MVCC 机制下,数据库中每条记录中都有几个隐藏字段,最常见的如 xmin、xmax
xmin: 在创建记录时,此值设置为插入tuple的事务ID
xmax: 默认值为0,在删除tuple时,为删除的tuple的事务ID
查询数据时显示指定位置 xmin 和 xmax 能看到隐藏列
select user_id, task_id, updated, xmin, xmax from user_task where user_id = 'UUBXJXXXWCEUU'
结果
--------------- ----------- ---------------------------- ------------ -------- | user_id | task_id | updated | xmin | xmax ||--------------- ----------- ---------------------------- ------------ --------|| UUBXJXXXWCEUU | 1005 | 2021-05-31 10:23:23.69 00 | 2723516899 | 0 || UUBXJXXXWCEUU | 1003 | 2021-05-31 10:23:23.682 00 | 2723516885 | 0 || UUBXJXXXWCEUU | 6 | 2021-05-31 10:23:23.666 00 | 2723516837 | 0 || UUBXJXXXWCEUU | 4 | 2021-05-31 10:25:31.684 00 | 2723870831 | 0 || UUBXJXXXWCEUU | 2 | 2021-05-31 10:23:23.646 00 | 2723516783 | 0 || UUBXJXXXWCEUU | 1 | 2021-05-31 10:23:23.639 00 | 2723516764 | 0 || UUBXJXXXWCEUU | 1004 | 2021-05-31 10:23:23.686 00 | 2723516893 | 0 || UUBXJXXXWCEUU | 1002 | 2021-05-31 10:23:23.679 00 | 2723516867 | 0 || UUBXJXXXWCEUU | 7 | 2021-05-31 10:23:23.671 00 | 2723516844 | 0 || UUBXJXXXWCEUU | 5 | 2021-05-31 10:23:23.662 00 | 2723516827 | 0 || UUBXJXXXWCEUU | 11 | 2021-05-29 07:11:26.992 00 | 2285410093 | 0 || UUBXJXXXWCEUU | 8 | 2021-05-29 07:11:26.982 00 | 2285410054 | 0 || UUBXJXXXWCEUU | 3 | 2021-05-31 10:23:23.653 00 | 2723516800 | 0 || UUBXJXXXWCEUU | 1001 | 2021-05-31 10:24:18.9 00 | 2723669084 | 0 || UUBXJXXXWCEUU | 10 | 2021-05-29 08:57:36.131 00 | 2306009087 | 0 || UUBXJXXXWCEUU | 9 | 2021-05-29 08:57:33.943 00 | 2306002176 | 0 | --------------- ----------- ---------------------------- ------------ --------
xmin 即为插入记录的事务ID,xmax 为 0 代表记录为最新有效版本。
Vacuum 机制的原因及理论
Vacuum 功能简介
Vacuum 有几项重要功能:
恢复或重用由更新或已删除的行占用的磁盘空间。
更新 PostgreSQL 查询规划器使用的数据统计信息。
更新可见性映射,从而加快索引扫描。(index-only scans)
避免由于事务ID或者混合事务ID丢失历史数据。
这些原因都要求执行不同频率和范围的任务 VACUUM 操作。
1)恢复磁盘空间
垃圾来自哪里?
因着数据库的 MVCC 多版本并发控制的概念,PostgreSQL 在删除/更新记录时是这样处理的:
删除:对数据记录进行标记删除,不会在物理存储中真实的删除它。
更新:将记录标记删除,并且插入新的记录。
示例:PostgreSQL 垃圾数据
更新前,有一条记录 Tuple1(xmin=1834,xmax=0),这个记录是由事务:1834 插入的。
此处执行的更新操作 事务:1835,没有删除掉 Tuple1,修改了 Tuple1 的 xmax 为自己的事务ID(xmin=1384, xmax=1835)
事务:1835插入了一条修改后的记录Tuple2(xmin=1835,xmax=0)
当 事务:1834 结束后,将不会有人用到 Tuple1,Tuple1 变成了垃圾数据。
使用 Standard Vacuum 进行清理会移除表及索引中的无效记录,并标记了将来重复使用的空间,上例的 Tuple1 就会被 Vacuum 发现并处理。
空间膨胀
数据失效后被 Vacuum 标记后可以被重复使用,但是如果 Vacuum 没有及时清理,同时短时间内有大量的更新删除操作,将会导致数据库在堆中创建大量的 Page,即使后续使用标准 Vacuum 清理,但这些空间一般不会直接返还给操作系统 —— 这就造成了空间膨胀
空间膨胀后只能只用 Vacuum Full 进行恢复。
Vacuum Full 即运行 vacuum 命令的时候加上 full 参数—— vacuum full
使用 Vacuum Full 清理会利用磁盘空间创建一个紧凑的没有垃圾数据的新副本,可以最小化表的大小(近似的:例如膨胀后 100 个页,仅使用了一半空间,那么 Vacuum Full 会创建 50 个新页,将数据全量复制过去)——会消耗大量磁盘空间,且复制表非常慢。
其它数据库也存在同样的问题吗?
是的,其它实现了 MVCC 数据库同样需要对失效的数据进行清理。
例如:Oracle 和 MySQL 的 InnoDB 引擎,与 PostgreSQL 的实现方式不同,它们将这些标记删除的数据移动到了回滚日志中,主表只保留行的最新数据。
MVCC 两种实现方式
一般 MVCC 的实现方式有 2 种
写新数据时,把旧数据转移到一个单独的地方,如回滚段中,其他人读数据时,从回滚段中把旧的数据读出来,如Oracle数据库和MySQL中的innodb引擎。
写新数据时,旧数据不删除,而是把新数据插入。PostgreSQL就是使用的这种实现方法。
第一种方案
优点
不会像 PostgreSQL 一样造成空间膨胀,也不要需要 vacuum 机制进行清除;
缺点
写入回滚日志会有新的“问题”,它会创造一个巨大的回滚段,需要定时的清理回滚日志。将数据写到回滚段会有更多的开销,且查询历史行版本数据也会相对缓慢。
第二种方案
优点
无论事务进行了多少操作,事务回滚可以立即完成;数据可以进行很多更新,不必像 Oracle 和 MySQL 的 Innodb 引擎那样需要经常保证回滚段不被用完。
缺点
旧版本的数据需要清理,否则会造成空间膨胀(在 PostgreSQL 9.x版本中已经增加了自动清理的辅助进程来定期清理);旧版本的数据可能会导致查询需要扫描的数据块增多,从而导致查询变慢。
两种实现各有利弊,不同的实现是数据库整体设计和侧重的考量。
2)生成分析信息
PostgreSQL 查询计划会利用一些统计数据来优化查询器,这些统计分析信息由 analyze 命令生成。
开启 autovacuum 后,它会自动调用命令进行分析。
需要注意的是 autovacuum 严格按照插入或更新的行数来调用,它不知道表上更新的字段是不是我们“感兴趣的”,也无法判断更新的分析是不是有意义的。
与用于空间恢复的清理一样,更高频率的更新往往更好。但也需要注意如果数据的分布没有太多的变化,也不需要特别频繁的更新。一个经验法则是考虑列内数据的最大值和最小值,例如“更新时间”字段,它的的最大值会一直增加,而其它字段可能变化区间范围很小。
可以在特定的表或者列上运行分析命令。但在实践中,最好只分析整个数据库,这是一个很快速的操作 —— 它会对表进行随机抽样,不会遍历整个表。
3)更新 Visibility Map(VM)
VM 用途
Vacuum 为每个表维护一个可见性映射,以跟踪哪些页只包含已知对所有活动事务可见的元组。这有两个目的:
首先,vacuum 本身可以在下一次运行时跳过这些页面,因为没有什么东西需要清理。
另外,可以被用于 Index-only Scan(仅索引扫描)
什么是仅索引扫描?
仅索引扫描(Index-only Scan)的意思是只读取索引而不需要查询表堆内的数据即可完成查询(最少的磁盘IO、效率最高)
查询如果满足两个条件,则将仅使用索引查询,不会出发随机堆访问。
索引类型支持,如 B-Tree,或 GiST、SP-GIST 的部分操作符。
查询仅使用索引列,例如:x, y 为索引列,z 不是索引列
select x, y from tab where x = 'key' and y < 42 -- 仅索引select x, y from tab where x = 'key' and z < 42 -- 触发堆查询
扩展:如果有一两个字段作为数据项跟索引Key的联系十分紧密
SELECT y FROM tab WHERE x = 'key';
可以使用 INCLUDE 关键字在创建索引的时候将这个字段也包含在索引中
CREATE INDEX tab_x_y ON tab(x) INCLUDE (y);
仅索引扫描应用可见性地图的简化流程:
更新及使用时机
由于 PostgreSQL 中检索后需要校验 MVCC 快照可见性,哪些数据可见,哪些数据已标记删除。
在 PostgreSQL 中,数据和索引是单独存储的。因为索引不包含元组可见性信息,索引普通的索引扫描需要为每个匹配项获取堆元组,以检查当前事务是否应该看到它。
可见性地图存储着两位数据,第一位设置(1|0)表明堆页没有空闲空间,即所有页内数据都可见。第二位设置(0|1)表明页内数据都已被冻结,全都可见,不需要清理。
Vacuum 会在清理后设置 Page 在可见性地图中对应的标识位,任何的更新删除操作都将导致 VM 状态位复原,如果标志位没有复原,说明 Page 自上次清理后没有无效数据
有了可见性地图,仅索引扫描首先检查可见性地图,如果知道页面上的所有元组都是可见的,那么可以跳过堆获取。可见性映射比堆小得多,因此即使堆非常大,也可以轻松地缓存它(一页两位表示)。
简而言之,考虑到这两个基本要求,只进行索引扫描是可能的,但只有当表堆页的大部分都设置了全可见映射位时,才会成功。但是,其中大部分行是不变的表是非常常见的,这使得这种扫描在实践中非常有用。
4)防止事务ID环绕问题
PostgreSQL 的 MVCC 事务语义依赖于能够比较事务ID(XID)编号:如何插入的 XID 大于当前事务的 XID 的行版本,那么这个变更是“将来的”,不应该对当前事务可见。
但由于事务ID大小有限(32位),集群运行很长一段时间(超过40亿个事务)后会遭受事务ID环绕:XID 计数器变为零,会突然的导致过去的事务似乎在未来,简言之,造成所有数据丢失 (实际上数据还在那里,但你如果无法获取到它),为了避免这种情况,有必要每20亿个事务时,至少清理一次每个数据库中的每个表。
在 PostgreSQL 中解决事务ID环绕的方法:事务 ID 是环绕的,像一个钟表,当一个事务发起,总是认为有一半事务是“过去”,另一半“事务” 在将来,比较事务新旧看事务的“年龄”,年纪小的事务总是新创建的。
如果一个数据过老,如图所示,事务1 就会成为 事务4 将来的事务,导致对 事务4 不可见。
解决的办法是借助 Vacuum,它会识别出这些存在很长时间的数据,并将记录 “冷冻”,被冷冻的数据不遵循 XID 比较规则,它将对所有事务可见。这就解决了事务环绕ID的问题。
当前事务ID及环绕次数
查询当前事务ID
appserver_mars> select (txid_current() % (2^32)::bigint)::text::xid ------------ | xid ||------------|| 1191485379 | ------------ SELECT 1Time: 0.043s
查询环绕次数
appserver_mars> select (txid_current() >> 32) AS xid_epoch; ------------- | xid_epoch ||-------------|| 10 | ------------- SELECT 1Time: 0.046s
通过最新插入的记录,查询记录的 xmin 也能知道最新的事务ID:
appserver_mars> select user_id, xmin, xmax from user_biding where user_id = 'UUTEST001'; ----------- ------------ -------- | user_id | xmin | xmax ||----------- ------------ --------|| UUTEST001 | 1276864929 | 0 | ----------- ------------ -------- SELECT 1Time: 0.065s
Vacuum 机制运行的全过程
Vacuum 与 Vacuum Full
Vacuum 分为 Standard Vacuum 与 Vacuum Full 两种,区别如下
Standard Vacuum
执行速度较快,能够与生产数据库并行运行(例如:SELECT、INSERT、UPDATE、DELETE 都不会受到影响,但是修改表的操作不能运行 ALTER TABLE)
不能减小膨胀后的空间。
运行时会找到很老的记录对它进行“冻结”。
Vacuum Full
能够回收更多的磁盘空间,但需要占用最多一倍的磁盘空间来运行,且运行的非常缓慢
会使用排他锁独占表,导致表不能读写,不能用于生产环境!
运行后所有的记录都会被“冻结”。
Autovacuum 自动运行
PostgreSQL 有一个可选的、并且非常推荐开启的特性,即 Autovacuum
“自动清理的后台程序” 实际由多个进程组成,有一个持久的守护进程,负责启动进行执行任务,如果有 N 个数据库,会为每个数据库会启动一个进程进行处理。每个进程启动间隔参数为 autovacuum_naptime(默认一分钟间隔),autovacuum_max_workers 为同一时刻最多启动清理进程的数量。
配置概览
# 是否启用 Autovacuumautovacuum = on# 在规定时长内未完成的 vacuum 予以记录日志(单位:毫秒,“-1” 不不记录,“0”每次都记录)。log_autovacuum_min_duration = -1# 同一时刻最多启动清理进程的数量autovacuum_max_workers = 3# 两次 Vacuum 间隔时间autovacuum_naptime = 1min# 触发 Vacuum 所需的最小更新或删除的最小元组数量# 触发规则(autovacuum_vacuum_scale_factor * table_size autovacuum_vacuum_threshold)autovacuum_vacuum_threshold = 50autovacuum_vacuum_scale_factor = 0.2# 触发 Vacuum 所需要插入的最小元组数量autovacuum_vacuum_insert_threshold = 1000autovacuum_vacuum_insert_scale_factor = 0.2# 触发 Analyze 所需插入、更新、删除的最小元组数量autovacuum_analyze_threshold = 50autovacuum_analyze_scale_factor = 0.1# 强制对数据库进行清理的 XID 上限值,表的 pg_class.relfrozenxid 字段可以实现的最大值。# 即使禁用 Autovacuum,系统也将启动 Autovacuum 流程以防止事务环绕。autovacuum_freeze_max_age = 200000000# 指定表的 pg_class.relminmxid 字段可达的最大值。#(Multixact:同一个元组相关联的事务ID可能有多个,为了在加锁(行共享锁)的时侯统一操作,PostgreSQL将与该元组相关联的多个事务ID组合起来用一个 MultiXactID 代替来管理)autovacuum_multixact_freeze_max_age = 400000000# 以毫秒计的时间长度,如果超过了开销限制,那么进程将睡眠此配置指定的时间#(如果值为 “-1” 则默认使用 vacuum_cost_delay 值)autovacuum_vacuum_cost_delay = 2ms# 系统维护一个内部的记数器,跟踪所执行的各种 I/O 操作的近似开销。如果积累的开销达到了 vacuum_cost_limit 声明的限制,那么执行这个操作的进程将睡眠 vacuum_cost_delay 指定的时间。然后它会重置记数器然后继续执行。(如果值为 “-1” 则默认使用 vacuum_cost_limit 值)autovacuum_vacuum_cost_limit = 400# 指定每个自动清理工作者进程能使用的最大内存量。如果指定值时没有单位,则以千字节为单位。其默认值为 -1,表示转而使用 `maintenance_work_mem` 的值,当运行在其他上下文环境中时,这个设置对 Vacuum 的行为没有影响。autovacuum_work_mem = -1maintenance_work_mem = 64MB
关于 maintenance_work_mem 参数的补充:
maintenance_work_mem 参数
指定在维护性操作(例如VACUUM、CREATE INDEX 和 ALTER TABLE ADD FOREIGN KEY)中使用的最大的内存量。 如果没有制定单位,则以千字节为单位,其默认值是 64 兆字节(64MB)。在一个数据库会话中,一个时刻只有一个这样的操作可以被执行,并且一个数据库安装通常不会有太多这样的操作并发执行, 把这个数值设置得比 work_mem 大很多是安全的,更大的设置可以改进清理和恢复数据库转储的性能。
注意当自动清理运行时,可能会分配最多达这个内存的 autovacuum_max_workers 倍,因此要小心不要把该默认值设置得太高。 通过独立地设置autovacuum_work_mem可能会对控制这种情况有所帮助。
触发方式
Autovacuum 会在两种情况下会被触发
当 Update、Delete 的 Tuples 数量超过 autovacuum_vacuum_scale_factor * table_size autovacuum_vacuum_threshold(Insert 配置参数同理)。
指定表上事务的最大年龄配置参数 autovacuum_freeze_max_age,默认为2亿,达到这个阀值将触发 autovacuum 进程,从而避免事务ID环绕。
Autovacuum 启动受到 autovacuum_vacuum_threshold(阈值) 和 autovacuum_vacuum_scale_factor(比例因子) 的影响。
每当死元组的数量,可以看作 pg_stat_all_tables.n_dead_tup,超过公式就会触发清理:
pg_stat_all_tables.n_dead_tup > autovacuum_vacuum_threshold pg_class.reltuples * autovacuum_vacuum_scale_factor
当满足上面的公式时,该表将被视为需要清理,该公式表示在清理之前,高达20%的表可能是死元组(当系数为 0.2,50行的阈值是为了防止非常频繁地清理微小的表)默认的比例因子适用于中小型表,但对于非常大的表则没有那么多(在10GB表上,这大约是2GB的死元组,而在1TB表上则是~200GB)
如果是大表,通常将比例因子设置的很小(例如:0.01),这样表中的数据变化达到 1% 时触发 Autovacuum
autovacuum_vacuum_scale_factor = 0.01autovacuum_vacuum_threshold = 50
或者放弃使用比例因子,完全用阈值来控制。(推荐)
autovacuum_vacuum_scale_factor = 0autovacuum_vacuum_threshold = 10000
这将生成10000个死元组后触发清理,带来的问题是在 postgresql.conf 中更改这些参数会影响所有表,并且不利于影响小表的清理(例如系统表)
当清理小表时,最简单的解决方案是完全忽略问题,即使忽略问题,整体效果仍然非常明显。
清理过程
Vacuum 清理过程很简单,它从数据文件中读取页面(默认8kB数据块),并检查它是否需要清理,如果没有死元组,页面就会被丢弃而不做任何更改,否则它被清理(死元组被删除)
Vacuum 最佳实践
一些管理员倾向于禁用 Autovacuum,设置 Schedule Vacuuming 在晚上空闲的时间执行清理。
这种方式的优点是尽可能减少清理对线上的影响,但完全关闭 Autovacuum 在一个问题 —— 无法应对意想不到的尖峰,会导致空间过渡膨胀,不通过 Vacuum Full 则没办法恢复已经膨胀的磁盘空间。
较好的方式是调整 Autovacuum 参数,使其有较高的触发阈值,减少平时的自动清理次数,同时能够应对突增的修改和删除。
基于成本的 Vacuum 策略
此特性的目的是允许管理员减少这些命令对并发数据库活动的I/O影响。
像 Vacuum 和 Analyze 这样的维护命令不需要快速完成,并且这些命令通常应该显著干扰数据库的其它操作。
默认情况下,手动执行 Vacuum 命令没有开启此功能,要启用它,需将 vacuum_cost_delay 变量设置为非零值。
成本核算基于 postgresql.conf 定义三个配置,这三个配置值是“成本”的度量,没有具体的单位。
# 当页面是从 shared_buffers 读取时的花费vacuum_cost_page_hit = 1# 当页面在 shared_buffers 找不到,需要从操作系统中读取时的花费vacuum_cost_page_miss = 10# 当 Vacuum 将清理后的脏数据块写会磁盘时需要的花费vacuum_cost_page_dirty = 20
如果数据库的性能、吞吐量较高,可以对数值进行调整,但通常不建议直接修改。
通过修改 vacuum_cost_limit 限制来进行成本限制就足够了。
设置清理者数量
autovacuum_max_workers 的建议值为 CPU核数/3。CPU 资源充足,I/O 性能较好时,可以适当加大。
vacuum_cost_limit 是对所有的工作者的整体限制,过多的增加工作者数量而不调整资源使用限制很可能会使清理速度降低。
设置 Autovacuum 的清理频率
比较理想的解决方案是建议在 postgresql.conf 中忽略比例因子,设置为较大的阈值:
autovacuum_vacuum_scale_factor = 0autovacuum_vacuum_threshold = 10000
然后根据各个表的 delete 和 update 频繁程度以及表的数据量单独为每个表设置阈值:
ALTER TABLE t SET (autovacuum_vacuum_threshold = 100)
PostgreSQL 的默认参数一般都很保守,因为默认值通常基于几年前的机器评估的。
另外由于更新频繁的大表和不经常变动的小表触发频率很难保持同步,没有适合所有场景的最优配置参数,需要结合实际情况,根据机器的配置和表的更新频率进行调整。
建议开启自动清理,不使用比例因子,只使用阈值触发,同时配置定时任务在空闲时间段触发清理。
Tips 总结
中等频率的 Standard Vacuum 比低频率的 Vacuum Full 更好。
如果数据库运行了很久,并且从来没有打开过 Autovacuum,那么需要在打开 Autovacuum 之前全库手动运行vacuum 和 analyze(可能要非常久的时间)。
请不要完全禁用 Autovacuum,除非真的知道自己在做什么,并且需要定期清理脚本,否则当问题发生时将不得不处理花费大量的时间处理,甚至可能需要停库、停机。
对于更新频繁的交易系统,如果系统资源充足,可以缩小 autovacuum_vacuum_scale_factor 与 autovacuum_vacuum_threshold,让 vacuum 更频繁的清理。
analyze 的触发不宜过于频繁,需要进行的评估,因为每一次触发都会从头开始分析统计。
使用 Alter table 设置参数要慎重,这会让系统变得复杂,不易维护。
Vacuum 线上示例
AWS Vacuum 资源消耗图例
一下截图为手动执行 vacuum 的资源消耗情况,蓝色为写入实例,橙色为读取实例
由上图可知,Vacuum 清理对于 CPU 的消耗很少,但 IO 的读取次数和吞吐量确实很高。
对比读取的 IO,可以看到 Vacuum 读取大量数据进行处理后会统一进行写回。
Mars 死亡元组与占比
SELECT relid, relname, n_dead_tup AS "死元组数", ( CASE WHEN n_live_tup > 0 THEN n_dead_tup :: float8 / n_live_tup :: float8 ELSE 0 END ) AS "死/活元组的比例" FROM pg_stat_all_tablesWHERE n_dead_tup > 50000;
结果
--------- -------------------------- ------------ ---------------------- | relid | relname | 死元组数 | 死/活元组的比例 ||--------- -------------------------- ------------ ----------------------|| 520422 | user_event_count | 61791 | 0.0288907289799853 || 193683 | user_card_collection | 1848855 | 0.0305172031736089 || 193655 | user_activity_status | 241437 | 0.0169121233916682 || 193584 | quiz_daily_coin_reward | 180611 | 0.00956191620142077 || 193749 | user_poem_challenge | 282308 | 0.0186522428504735 || 193611 | quiz_record | 81272 | 0.0271187074101287 || 509654 | type_coin_history | 784974 | 0.00961449261907086 || 193712 | user_daily_history | 123150 | 0.0152117001752279 || 193728 | user_guess | 55451 | 0.0110665309037032 || 193664 | user_asset | 631261 | 0.0417559539480038 || 193771 | user_task | 1023871 | 0.00541445520793488 || 193731 | user_pet_reward | 197843 | 0.0166741492996399 || 279214 | quiz_total_coin_reward | 78582 | 0.0287905527770013 || 193701 | user_coin | 308302 | 0.0195438620246524 || 193483 | activities_daily_process | 88327 | 0.000704609598801467 || 193691 | user_challenge | 255399 | 0.0168226854999805 || 193570 | koi_process | 369251 | 0.0750457234012154 || 193762 | user_status | 94934 | 0.00605523084395569 || 193759 | user_red_envelope | 116598 | 0.00803769093721015 | --------- -------------------------- ------------ ---------------------- SELECT 19
最近清理时间
在 pg_stat_all_tables 表中保存着最后一次自动清理和手动清理的执行时间。
appserver_mars> select relid, relname, last_vacuum, last_autovacuum from pg_stat_all_tables where relname = 'user_task' --------- ----------- --------------- ------------------------------ | relid | relname | last_vacuum | last_autovacuum ||--------- ----------- --------------- ------------------------------|| 193771 | user_task | <null> | 2021-07-05 01:38:18.87692 00 | --------- ----------- --------------- ------------------------------
定时处理脚本,根据业务需要进行
#!/bin/bash#date=`date "%Y-%m-%d %H:%M:%S"` echo "begin time is: $date" >>/tmp/pg_lqdb_vacuum.log pg_db=yewu_dbods_schema=demo_odsods_tables='weather tbl_test'for table in $ods_tables;do psql -U postgres -d $pg_db -c "vacuum $ods_schema.$table;" >>/tmp/pg_lqdb_vacuum.log echo "table $ods_schema.$table has finished vacuum.">>/tmp/pg_lqdb_vacuum.logdone本文转载来源于:https://blog.yasking.org/a/postgresql-vacuum.html,版权归原作者所有
大话数据库MySQL项目实战的那几个点
一、MySQL简介
MySQL一般特制完整的MySQLRDBMS,是一个开源的关系型数据库管理系统(Relational Database Management System),现在属于Oracle公司。随着MySQL功能的不断完善,性能不断提高,又有开源免费的优势,越来越多的企业选择使用MySQL,而放弃商用收费的Oracle。
二、MySQL结构
1、逻辑结构
MySQL采用的是客户/服务器体系结构,因此实际使用时,有两个程序:
1. 一个是MySQL服务器程序,指的是mysqlId程序,运行在数据库服务器上,负责在网络上监听并处理来自客户端的服务请求根据这些请求去访问数据库的内容,再把有关信息回传给客户;
2. 另一个程序是MySQL客户端程序,负责连接到数据库服务器,并通过发出命令来告知服务器它想要的操作。
从下面简单的逻辑图中可以看出,MySQL内部大致分为三层:
1. 最上层是大部分基于网络的C/S服务都有的部分,比如连接处理、授权认证、安全等;
2. 第二层包括MySQL的很多核心服务功能,包括查询解析、分析、优化、缓存以及所有的内置函数(例如,日期、时间、数学和加密函数),所有的跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
3. 第三层包含了存储引擎,存储引擎负责MySQL中欧数据的存储和提取,是数据库中非常重要非常核心的部分,也是MySQL区别与其他数据库的一个重要特性。
不同的存储引擎有个字的特点,MySQL支持插入式的存储引擎,可以根据实际情况选择最合适的存储引擎。不过目前对于绝大部分应用来说,MySQL默认的存储引擎InnoDB应该就是其最佳选择。我觉得刚开始学习的时候介绍很多不常用甚至不会用到的存储引擎虽然可能会横向比较,让开发人员更了解每个存储引擎的特性,但是这样对开发人员造成的困扰更大,还不如专心学习一种用途最广泛的存储引擎,屏蔽其他干扰,学到一定深度后再了解其他存储引擎的不同点。
2、体系结构
具体查看MySQL在物理上的体系结构,从上到下依次是:
1. 连接池组件
2. 管理服务和工具组件、SQL接口组件、查询分析器组件、优化器组件、缓冲组件
3. 插件式存储引擎
4. 物理文件
三、 数据库和实例
区分两个词
数据库指物理上的存储文件,实例是用来操作数据库文件的。在MySQL数据库中,实例与数据库通常是一一对应的,这时两个词可以互换,但在集群情况下,可能存在一个数据库被对个数据实例使用的情况.
MySQL是单进程多线程架构的数据库,实例在系统上的表现就是一个进程。
四、MySQL不得不说的八个陷阱
Mysql安装简单,速度较快,功能丰富。另外它还是开源运动的标杆,它的伟大成就向我们展示了一个成功的公司是可以建立在开源代码之上的。
然而用过mysql的人都曾对着显示器挥舞过拳头。但你不可能发明一种每秒能保存成千上万行互联网数据,并且一点错误都没有的技术吧。
以下列举了8个开源关系型数据库的缺陷,其中不仅限于MySQL,还有是针对关系型数据库的。只有明白了关系型数据库和MySQL,才能更好地避免在使用MySQL中尽量少地遇到一些意外。
1、根深蒂固的bugs
任何大的软件包都有 bug。但稍微深入了解一下,就会发现和 Mysql 相关的 bugs 自成体系。突然你就需要留心,因为 NULL 并不是以同样的方式出现,外键约束也没有像你想像的那样执行,连主键自动增长也会出错。
小问题大量存在,而且并不总是可以修复,这就是为什么一些人保持一个列表。还好 MySQL 维护着一个非常好的 bug 报告系统,让我们可以知道我些我们无法想像的事情,知道其他人也在经受同样的磨难。
2、关系表的不灵活性
关系表具有条理性,条理性是好的——但是,它使得程序员不得不编造或硬塞一些数据到已经定义好模式的列中。NoSQL开始越来越受到欢迎的原因之一,就是它为程序员提供了足够的灵活性,来加速数据库的使用。如果一个街道地址需要增加一行,那么,你可以将它很容易地插入到一个NoSQL文档中。如果你想添加一个完整的新的数据块,无论它包含什么内容,文档模型也可以原封不动地接受你的数据,而不必改为它要求的数据格式。
试想一下,你用整数格式建立了一个全部是邮编的表格。这个表是十分高效的,它执行的规则也很好。突然一次,有人上传了一个使用了连字符的九位数邮编。或者还有可能,你得到了一位来自加拿大客户的信件,上面写有邮政编码。
这时,一切都乱了。老板要求网站要在几小时内恢复正常工作。然而,现在已经没有时间来重建数据库。程序员可以做什么?也许,可以使用黑客手段把加拿大邮政编码由base64的数字格式改为base 10格式?或者设置一个使用转义编码的辅助表格,用来说明真正的邮政编码或者其他?谁知道呢?到处都有黑客,他们都是危险的。但你没有时间来搞定它。
MySQL的关联规则让每个人都诚实和谨慎,但它能强制我们避开易受攻击和欺骗的麻烦。
3、存储引擎混乱
总体来说,Mysql的存储引擎接口定义还算良好的。MySQL不是实际上的同一的数据库。它是由几个数据库组成,它们的大多数细节都被统一的表面掩盖了。开始时有一个MyISAM引擎,它很快但在前后一致上不能做到完备。有时你需要速度并且可以接受不一致的结果时是很好的。
当人们需要更多时,具备完整事务支持的Inno DB出现了。但这还不够。现在,它可能有20种存储引擎的选择——这足以使一个数据库管理员疯狂。当然,有时在不同的存储引擎之间切换而不必重写你的SQL是很好的,但是切换后总会带来混乱。这个表格我选择的引擎是MyISAM还是innoDB呢?或者,我决定输出的数据是CSV格式的吗?
4、JOIN联合查询
曾经,将数据分表保存是计算机科学史上的伟大创新。分开后的表不仅结构简单,使用上也简化了许多。但它却需要使用join语句来进行查询。
sql通过一系列join构建的复杂查询将开发者推入了困惑与绝望的深渊。而且存储引擎也需要以最优的方式来高效地解析join语句。开发者需要绞尽脑汁编写查询语句,然后数据库对其进行解析。
这就是很多注重运行速度的开发者放弃数据分表转而使用不规范数据表的原因。不区分数据实体,将所有数据保存到一个大表中——以避免复杂的查询。这样确实很快,并且服务器也不会耗尽内存。
现在的磁盘空间很廉价。8TB的磁盘已经在售,更大容量的也将上市。我们不再需要为使用join而绞尽脑汁了。
5、分支的混乱
毋庸置疑,一个可靠的、得到良好支持的MySQL分支,可以带来竞争和选择,但是它也引起困惑和混乱。更糟糕的是,一个称为MariaDB的MySQL分支,由Monty Widenius维护着。他同样也在参与编写MySQL。那么,Maria DB是真正独立的值得我们拥护的吗?或者它是MySQL?我们是否应该坚持使用由创建原始mysql数据库的组织运营的核心代码?或者我们应该加入那些被认为更聪明的,往往很酷的背叛者?
如何获取关于兼容性的信息?虽然Maria DB和MySQL十分相似,但它们之间也有差异。这就是大家一直都在争论它的原因。在性能方面,在我们查询的范围内,在两个阵营中,也许它们的工作方式相同,但也许不同,也许将来会不同。
6、开发MySQL的动机
虽然MySQL是一款成功的开源产品,但它仍属于商业中的一款产品,专业开发者需要靠它来获得利益,当然,最直接的利益就是薪资。当大多数用户在持续地享受开源许可证带来的最佳体验时,毫无疑问这家公司还在为赚取足够的钱来维持运营而努力。这导致自由代码在“社区版”和出售给企业的完整产品之间产生了奇怪的分岐。
我们应该对这款产品付钱吗?这种在社区版开展经营的行为是否公平?企业版中额外的功能是不是一个噱头,以引诱我们不断付费的呢?这至少说明一点,它是另一些需要回答的问题:选用哪个版本?遵照哪种许可证?选用它的哪个功能集?
7、原生JSON支持的缺乏
通过安装MySQL查看其年龄,然后你就知道需要添加哪些驱动程序使它变得可用。MySQL通常在3306端口上通信,一般输出的是它本身难以理解的格式化数据。如果要让你的代码和它通信,你必须添加另一层代码,将MySQL的语言转换成有用的东西。这些层的代码,以库的形式分发,经常需要人们购买一个商业许可证。
现代数据存储层通常直接以JSON通信。虽然MySQL和Maria DB现在有能力解析SQL中的JSON部分,但这还远远不够,原生的JSON接口已经被广泛使用于CouchDB、MongoDB,或任何最新的工具中。
8、封闭源和专有模块的兴起
虽然MySQL是开源的,但除了一些在”开源核心“周边开发的一些较新的、非开源的代码和专有模块。程序员也需要赚钱、需要生活,Oracle需要拿它的辛苦成果来换钱,这是一种现实,也是商业的性质。使用MySQL你也不可以免费得到任何东西。
要求MySQL始终坚持在一个很高的标准上,这有点不公平,因为开源的成功可能是一个圈套。它开始可以免费,但并不意味着它可以始终免费。如果企业需要更多新的功能,他们就要通过各种方式付费来获取。有时向Oracle付费,比自己来编写代码要便宜得多。有时商业的、不开源的代码是有意义的。
MySQL虽然作为一个成功的开源系统,但以上这些问题也总不可避免地出现,这就需要我们在它们发生之前有个深刻的认识,才能在今后的应用中避免不必要的麻烦。
在此我向大家推荐一个架构学习交流群。交流学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
五、MySQL分布式集群搭建
1 准备集群搭建环境
使用6台虚拟机来搭建MYSQL集群,相应的实验环境与对应的MYSQL节点之间的对应关系如下图所示:
管理节点(MGM):这类节点的作用是管理MySQLCluster内的其他节点,如提供配置数据,并停止节点,运行备份等。由于这类节点负责管理其他节点的配置,应该在启动其他节点之前启动这类节点。MGM节点是用命令“ndb_mgmd”启动的;
数据节点(NDB):这类节点用于保存Cluster的数据,数据节点的数目与副本的数目相关,是片段的倍数。例如,对于两个副本,每个副本有两个片段,那么就有4个数据节点,没有必要设定过多的副本,在NDB中数据会尽量的保存在内存中。数据节点使用命令“ndb”启动的;
SQL节点:这是用来访问Cluster数据的节点,对于MySQL Cluster,客户端节点是使用NDB Cluster存储引擎的传统MySQL服务器。通常,SQL节点使用命令“mysqld-ndbcluster”启动的;
2、准备安装包
在官网上下载mysql的安装包: mysql-cluster-gpl-7.4.11-Linux-glibc2.5-x86_64.tar.gz,并进行解压。
3、集群搭建流程
1]将上述安装包解压出来的文件都移到/usr/local/mysql下;
2]运行script目录下的mysql-install-db.sh脚本,运行命令为./mysql-install-db.sh --user=root--basedir =/usr/local/mysql --datadir=/usr/local/mysql;注意其中用户为root的名称需要跟配置文件my.cnf中的相同;
在管理节点,数据节点,SQL节点上都执行上述安装命令,从而完成对mysql的安装;
4、集群配置与启动
1]在管理节点上需要完成对于集群整体的配置配置:在/var/lib/mysql-cluster/config.ini中实现如下的配置信息:
2]在数据节点中需要在my.cnf中完成对于数据节点的相关配置信息,如下:
需要指明配置的数据节点的根目录,数据目录,socket连接配置,用户配置,以及对应的管理节点的ip地址配置;将配置完成的配置文件移动到/etc/my.cnf,完成;
3]在SQL节点上完成对于SQL节点的配置信息,同样的是在my.cnf中完成相应配置信息,并将配置文件移动到/etc/my.cnf中,相应的配置信息的设定如下所示:
完成以上配置后,就可以启动集群中的各个节点了。
5、集群启动
在启动mysql集群的时候,注意首先要启动管理节点,并依次启动其他等若干个节点,相应的启动步骤如下:
1]在管理节点上,切换到/usr/local/mysql/bin目录下,执行ndb_mgmd -f /var/lib/mysql-cluster/config.ini命令,完成管理节点的启动;
2]在各个数据节点上,切换到/usr/local/mysql/bin目录下,执行ndbd --initial(第一次启动时,否则执行ndbd即可),完成对数据节点的启动;
3]在各个SQL节点上,同样切换到/usr/local/mysql/bin目录下,执行mysqld_safe --user=root完成启动;
4]在管理节点上运行ndb_mgm命令,进入数据库管理的客户端,输入show命令,查看与之相连接的各个节点的状态;
5]在SQL节点上分别进入系统的安全状态,并完成对root用户的密码修改,运行以下指令,进行密码修改:
A use mysql,切换到mysql数据库;
B UPDATE user SET Password = PASSWORD('123456')WHERE user = 'root';从而实现对root密码的修改;
C flush privilege,完成修改;
6]修改使得任意主机都能连得上mysql,进行如下修改,同样安装第5步进入安全模式,并完成相应的修改,如下:
grant all on‘*.*’to ‘root@'%' identified by '123456';
这样就可以使得任意一个主机都可以通过root用户来登录mysql了;
6、集群测试
在集群上的一个SQL节点上执行创建数据库,并创建一张表,并完成相应的数据插入,如下:
A create database ctest; //创建数据库
B create table test(
id int primarykey; //创建一张表
);
C insert into test (id)values(1); //完成数据插入
登录另外一个SQL节点,并执行SQL查询操作,看数据库中是否已经有数据,如下:
select * from ctest;
如果有数据,表示数据插入成功;
7、关闭集群
1]首先关闭管理节点和数据节点,需要在管理节点上执行命令,如下:./ndb_mgm -e shutdown;
2]然后关闭SQL节点,在SQL节点上执行命令/usr/local/mysql/support-fies/mysql.server stop(其中/usr/local/mysql/是mysql的安装目录).从而关闭SQL节点
在此我向大家推荐一个架构学习交流群。交流学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
六、MySQL 的最佳实践
数据库操作是当今 Web 应用程序中的主要瓶颈。 不仅是 DBA(数据库管理员)需要为各种性能问题操心,程序员为做出准确的结构化表,优化查询性能和编写更优代码,也要费尽心思。 在本文中,我列出了一些针对程序员的 MySQL 优化技术。
在我们开始学习之前,我补充一点:你可以在 Envato Market 上找到大量的 MySQL 脚本和实用程序。
1.优化查询的查询缓存
大部分MySQL服务器都有查询缓存功能。这是提高性能的最有效的方法之一,这是由数据库引擎私下处理的。当同一个查询被多次执行,结果会直接从缓存里提取,这样速度就很快。
主要的问题是,这对程序员来说太简单了,不容易看到,我们很多人都容易忽略。我们实际上是可以组织查询缓存执行任务的。
查询缓存在第一行不执行的原因在于CURDTE()功能的使用。这适用于所有的非确定性功能,就像NOW()和RAND()等等。。。因为功能返回的结果是可变的。MySQL决定禁用查询器的查询缓存。我们所需要做的是通过添加一额外一行PHP,在查询前阻止它发生。
2. EXPLAIN你的选择查询
使用EXPLAIN关键词可以帮助了解MySQL是怎样运行你的查询的。这有助于发现瓶颈和查询或表结构的其它问题。
EXPLAIN的查询结果会展示哪一个索引被使用过,表示怎样扫描和储存的,等等。。。
选择一个SELECT查询(一个有连接的复杂查询会更好),在它的前面添加关键词EXPLAIN,这样就可以直接使用数据库了。结果会以一个漂亮的表来展示。例如,就好比我执行连接时忘了添加一栏的索引:
现在它只会从表2里面扫描9和16行,而非扫描7883行。经验法则是乘以所有“行”那一栏的数字,你的查询性能会跟结果数字成比例的。
3. 获取唯一行时使用LIMIT 1
有时当你查表时,你已经知道你正在查找的结果只有一行。你可能正在获取唯一记录,或者你可能只是查询是否存在满足你的WHERE子句条件的记录。
在这种情况下,将LIMIT 1添加到查询条件中可以提高性能。这样,数据库引擎将在找到刚刚第一个记录之后停止扫描记录,而不是遍历整个表或索引。
4. 索引搜索字段
索引不仅仅是为了主键或唯一键。如果你会在你的表中按照任何列搜索,你就都应该索引它们。
正如你所看到的,这个规则也适用于如 “last_name LIKE ‘a%’”的部分字符串搜索。当从字符串的开头搜索时,MySQL就可以使用那一列的索引。
你也应该明白什么样搜索可以不使用有规律的索引。例如,当搜索一个单词时(例如,”WHERE post_content LIKE ‘%apple%’”),你将不会看到普通索引的好处。你最好使用 mysql 全文搜索或者构建你自己的索引解决方案。
5. 索引并对连接使用同样的字段类型
如果你的应用程序包含许多连接查询, 你需要确保连接的字段在两张表上都建立了索引。 这会影响MySQL如何内部优化连接操作。
此外,被连接的字段,需要使用同样类型。例如, 如果你使用一个DECIMAL字段, 连接另一张表的INT字段, MySQL将无法使用至少一个索引。 即使字符编码也需要使用相同的字符类型。
6. 不要ORDER BY RAND()
起初这是一个听起来挺酷的技巧, 让许多菜鸟程序员陷入了这个陷阱。但你可能不知道,一旦你开始在查询中使用它,你创建了非常可怕的查询瓶颈。
如果你真的需要对结果随机排序, 这有一个更好的方法。补充一些额外代码,你将可以防止当数据成指数级增长时造成的瓶颈。关键问题是,MySQL必须在排序之前对表中的每一行执行RAND()操作(这需要处理能力),并且仅仅给出一行。
所以挑选一个小于结果数的随机数,并将其用作LIMIT子句中的偏移量。
7. 避免使用SELECT *
从数据表中读取的数据越多,查询操作速度就越慢。它增加了磁盘操作所需的时间。此外,当数据库服务器与Web服务器分开时,由于必须在服务器之间传输数据,将会有更长的网络延迟。
这是一个好习惯:当你使用SELECT语句时总是指定你需要的列。
8. 几乎总是有一个id字段
在每个以id列为PRIMARY KEY的数据表中,优先选择AUTO_INCREMENT或者INT。 也可以优选使用UNSIGNED,因为该值不能为负的。
即使你拥有一个具有唯一用户名字段的用户表,也不要将其作为主键。 VARCHAR字段作为主键(检索)速度较慢。通过内部ID引用所有的用户数据,你的代码中将更加结构化。
有些后台操作是由MySQL引擎本身完成的,它在内部使用主键字段。当数据库设置越复杂(集群,分区等…),这就变得更加重要了。
这个规则的一个可能的例外是“关联表”,用于两个表之间的多对多类型的关联。例如,“posts_tags”表中包含两列:post_id,tag_id,用于保存表名为“post”和“tags”的两个表之间的关系。这些表可以具有包含两个id字段的PRIMARY键。
9. 相比VARCHAR优先使用ENUM
ENUM枚举类型是非常快速和紧凑的。在内部它们像TINYINT一样存储,但它们可以包含和显示字符串值。这使他们成为某些领域的完美候选。
如果有一个字段只包含几种不同的值,请使用ENUM而不是VARCHAR。例如,它可以是名为“status”的列,并且只包含诸如“active”,“inactive”,“pending”,“expired”等的值…
关于如何重构你的数据表,甚至有一种方法是可以从MySQL本身得到“建议”。 当你有一个VARCHAR字段,它实际上建议你将该列类型更改为ENUM。这通过调用PROCEDURE ANALYZE()来完成。
在此我向大家推荐一个架构学习交流群。交流学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
10. 使用PROCEDURE ANALYSE()获取建议
PROCEDURE ANALYSE() 将使用MySQL分析列结构和表中的实际数据,为你提供一些建议。它只有在数据表中有实际数据时才有用,因为这在分析决策时很重要。
例如,如果你创建了一个INT类型的主键,但没有太多行,MySQL则可能建议您改用MEDIUMINT。或者如果你使用VARCHAR字段,如果表里只有很少的取值,你可能会得到一个建议是将其转换为ENUM。
你也可以在其中一个表视图中单击phpmyadmin中的“建议表结构”链接来执行此操作。
请记住,这些只是建议。 如果你的数据表变得越来越大,他们甚至可能不是正确的建议。至于如何修改最终是你来决定。
11. 如果可以的话使用NOT NULL
除非你有非常重要的理由使用NULL值,否则你应该设置你的列为NOT NULL。
首先,问一下你自己在空字符串值和NULL值之间(对应INT字段:0 vs. NULL)是否有任何的不同.如果没有理由一起使用这两个,那么你就不需要一个NULL字段(你知道在Oracle中NULL和空字符串是一样的吗?)。
NULL列需要额外的空间,他们增加了你的比较语句的复杂度。如果可以的话尽量避免它们。当然,我理解一些人,他们也许有非常重要的理由使用NULL值,这不总是一件坏事。
摘自MySQL 文档:
“行空列需要额外的空间来记录它们的值是否为空。 对于MyISAM表,每个NULL列需要一点额外的,围捕到最近的字节”。
12. 预处理语句
使用预处理语句有诸多好处,包括更高的性能和更好的安全性。
预处理语句默认情况下会过滤绑定到它的变量,这对于避免SQL注入攻击极为有效。当然你也可以指定要过滤的变量。但这些方法更容易出现人为错误,也更容易被程序员遗忘。这在使用框架或 ORM 的时候会出现一些问题。
既然我们关注性能,那就应该说说这个方面的好处。当在应用中多次使用同一个查询的时候,它的好处特别明显。既然向同一个预备好的语句中传入不同的参数值,MySQL 对这个语句也只会进行一次解析。
同时,最新版本的 MySQL 在传输预备好的语句时会采用二进制形式,这样做的作用非常明显,而且对减少网络延迟很有帮助。
曾经有一段时间,许多程序员为了一个重要的原因则避免使用预处理语句。这个原因就是,它们不会被MySQL 缓存。不过在 5.1 版本的某个时候,查询缓存也得到的支持。
想在 PHP 中使用预处理语句,你可以看看 mysqli 扩展 或使用数据抽象层,如 PDO。
13. 无缓冲查询
通常当你从脚本执行一个查询,在它可以继续后面的任务之前将需要等待查询执行完成。你可以使用无缓冲的查询来改变这一情况。
在PHP 文档中对 mysql_unbuffered_query() f函数有一个很好的解释:
“mysql_unbuffered_query()发送SQL查询查询MySQL没有自动抓取和缓冲结果行mysql_query()。 这节省了大量的内存生产大型结果集的SQL查询,你可以在结果集后立即开始工作第一行被检索到的是你不必等到完整的SQL查询已经完成。”
然而,它有一定的局限性。你必须在执行另一个查询之前读取所有的行或调用mysql_free_result() 。另外你不能在结果集上使用mysql_num_rows() 或 mysql_data_seek() 。
14. 使用 UNSIGNED INT 存储IP地址
很多程序员没有意识到可以使用整数类型的字段来存储 IP 地址,所以一直使用 VARCHAR(15) 类型的字段。使用 INT 只需要 4 个字节的空间,而且字段长度固定。
必须确保列是 UNSINGED INT 类型,因为 IP 地址可能会用到 32 位无符号整型数据的每一个位。
在查询中可以使用 INET_ATON() 来把一个IP转换为整数,用 INET_NTOA() 来进行相反的操作。在 PHP 也有类似的函数,ip2long() 和 long2ip()。
15. 固定长度(静态)的表会更快
(译者注:这里提到的表的长度,实际是指表头的长度,即表中每条数据占用的空间大小,而不是指表的数据量)
如果表中所有列都是“固定长度”,那么这个表被认为是“静态”或“固定长度”的。不固定的列类型包括 VARCHAR、TEXT、BLOB等。即使表中只包含一个这些类型的列,这个表就不再是固定长度的,MySQL 引擎会以不同的方式来处理它。
固定长度的表会提高性能,因为 MySQL 引擎在记录中检索的时候速度会更快。如果想读取表中的某一地,它可以直接计算出这一行的位置。如果行的大小不固定,那就需要在主键中进行检索。
它们也易于缓存,崩溃后容易重建。不过它们也会占用更多空间。例如,如果你把一个 VARCHAR(20) 的字符改为 CHAR(20) 类型,它会总是占用 20 个字节,不管里面存的是什么内容。
你可以使用“垂直分区”技术,将长度变化的列拆分到另一张表中。来看看:
16. 垂直分区
垂直分区是为了优化表结构而对其进行纵向拆分的行为。
示例 1: 你可能会有一张用户表,包含家庭住址,而这个不是一个常用数据。这时候你可以选择把表拆分开,将住址信息保存到另一个表中。这样你的主用户表就会更小。如你所知,表越小越快。
示例 2: 表中有一个 “last_login” 字段,用户每次登录网站都会更新这个字段,而每次更新都会导致这个表缓存的查询数据被清空。这种情况下你可以将那个字段放到另一张表里,保持用户表更新量最小。
不过你也需要确保不会经常联合查询分开后的两张表,要不然你就得忍受由这带来的性能下降。
17. 拆分大型DELETE或INSERT语句
如果你需要在网站上执行大型DELETE或INSERT查询,则需要注意不要影响网络流量。当执行大型语句时,它会锁表并使你的Web应用程序停止。
Apache运行许多并行进程/线程。 因此它执行脚本效率很高。所以服务器不期望打开过多的连接和进程,这很消耗资源,特别是内存。
如果你锁表很长时间(如30秒或更长),在一个高流量的网站,会导致进程和查询堆积,处理这些进程和查询可能需要很长时间,最终甚至使你的网站崩溃。
如果你的维护脚本需要删除大量的行,只需使用LIMIT子句,以避免阻塞。
18.越少的列越快
对于数据库引擎,磁盘可能是最重要的瓶颈。更小更紧凑的数据、减少磁盘传输量,通常有助于性能提高。
MySQL文档Storage Requirements 有所有数据类型清单。
如果已知表具有很少的行,则没有理由是主键类型为INT,可以用MEDIUMINT、SMALLINT代替,甚至在某些情况下使用TINYINT。 如果不需要完整时间记录,请使用DATE而不是DATETIME。
确保留下合理的扩展空间,不然你可能会像Slashdot这样。
19. 选择正确的存储引擎
MySQL有两个主要存储引擎,MyISAM和InnoDB。 每个都有自己的优点和缺点。
MyISAM适用于读取繁重的应用程序,但是当有很多写入时它不能很好地扩展。 即使你正在更新一行的一个字段,整个表也被锁定,并且在语句执行完成之前,其他进程甚至无法读取该字段。 MyISAM在计算SELECT COUNT(*)的查询时非常快。
InnoDB是一个更复杂的存储引擎,对于大多数小的应用程序,它比MyISAM慢。 但它支持基于行的锁定,使其更好地扩展。 它还支持一些更高级的功能,比如事务。
● MyISAM存储引擎
● InnoDB存储引擎
20. 使用对象关系映射器(ORM, Object Relational Mapper)
通过使用ORM(对象关系映射器),你可以获得一定的性能提升。ORM可以完成的一切事情,手动编码也可完成。但这可能意味着需要太多额外的工作,并且需要高水平的专业知识。
ORM以“延迟加载”著称。这意味着它们仅在需要时获取实际值。但是你需要小心处理他们,否则你可能最终创建了许多微型查询,这会降低数据库性能。
ORM还可以将多个查询批处理到事务中,其操作速度比向数据库发送单个查询快得多。
目前我最喜欢的PHP-ORM是Doctrine。我写了一篇关于如何安装Doctrine与CodeIgniter的文章(install Doctrine with CodeIgniter)。
21. 小心使用持久连接
持久连接意味着减少重建连接到MySQL的成本。 当持久连接被创建时,它将保持打开状态直到脚本完成运行。 因为Apache重用它的子进程,下一次进程运行一个新的脚本时,它将重用相同的MySQL连接。
理论上看起来不错。 但从我个人(和许多其他人)的经验看来,这个功能可能会导致更多麻烦。 你可能会出现连接数限制问题、内存问题等等。
Apache总是并行运行的,它创建许多子进程。 这是持久连接在这种环境中不能很好工作的主要原因。 在你考虑使用mysql_pconnect()之前,请咨询你的系统管理员。
大话数据库MySQL项目实战的那几个点
一、MySQL简介
MySQL一般特制完整的MySQLRDBMS,是一个开源的关系型数据库管理系统(Relational Database Management System),现在属于Oracle公司。随着MySQL功能的不断完善,性能不断提高,又有开源免费的优势,越来越多的企业选择使用MySQL,而放弃商用收费的Oracle。
二、MySQL结构
1、逻辑结构
MySQL采用的是客户/服务器体系结构,因此实际使用时,有两个程序:
1. 一个是MySQL服务器程序,指的是mysqlId程序,运行在数据库服务器上,负责在网络上监听并处理来自客户端的服务请求根据这些请求去访问数据库的内容,再把有关信息回传给客户;
2. 另一个程序是MySQL客户端程序,负责连接到数据库服务器,并通过发出命令来告知服务器它想要的操作。
从下面简单的逻辑图中可以看出,MySQL内部大致分为三层:
1. 最上层是大部分基于网络的C/S服务都有的部分,比如连接处理、授权认证、安全等;
2. 第二层包括MySQL的很多核心服务功能,包括查询解析、分析、优化、缓存以及所有的内置函数(例如,日期、时间、数学和加密函数),所有的跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
3. 第三层包含了存储引擎,存储引擎负责MySQL中欧数据的存储和提取,是数据库中非常重要非常核心的部分,也是MySQL区别与其他数据库的一个重要特性。
不同的存储引擎有个字的特点,MySQL支持插入式的存储引擎,可以根据实际情况选择最合适的存储引擎。不过目前对于绝大部分应用来说,MySQL默认的存储引擎InnoDB应该就是其最佳选择。我觉得刚开始学习的时候介绍很多不常用甚至不会用到的存储引擎虽然可能会横向比较,让开发人员更了解每个存储引擎的特性,但是这样对开发人员造成的困扰更大,还不如专心学习一种用途最广泛的存储引擎,屏蔽其他干扰,学到一定深度后再了解其他存储引擎的不同点。
2、体系结构
具体查看MySQL在物理上的体系结构,从上到下依次是:
1. 连接池组件
2. 管理服务和工具组件、SQL接口组件、查询分析器组件、优化器组件、缓冲组件
3. 插件式存储引擎
4. 物理文件
三、 数据库和实例
区分两个词
数据库指物理上的存储文件,实例是用来操作数据库文件的。在MySQL数据库中,实例与数据库通常是一一对应的,这时两个词可以互换,但在集群情况下,可能存在一个数据库被对个数据实例使用的情况.
MySQL是单进程多线程架构的数据库,实例在系统上的表现就是一个进程。
四、MySQL不得不说的八个陷阱
Mysql安装简单,速度较快,功能丰富。另外它还是开源运动的标杆,它的伟大成就向我们展示了一个成功的公司是可以建立在开源代码之上的。
然而用过mysql的人都曾对着显示器挥舞过拳头。但你不可能发明一种每秒能保存成千上万行互联网数据,并且一点错误都没有的技术吧。
以下列举了8个开源关系型数据库的缺陷,其中不仅限于MySQL,还有是针对关系型数据库的。只有明白了关系型数据库和MySQL,才能更好地避免在使用MySQL中尽量少地遇到一些意外。
1、根深蒂固的bugs
任何大的软件包都有 bug。但稍微深入了解一下,就会发现和 Mysql 相关的 bugs 自成体系。突然你就需要留心,因为 NULL 并不是以同样的方式出现,外键约束也没有像你想像的那样执行,连主键自动增长也会出错。
小问题大量存在,而且并不总是可以修复,这就是为什么一些人保持一个列表。还好 MySQL 维护着一个非常好的 bug 报告系统,让我们可以知道我些我们无法想像的事情,知道其他人也在经受同样的磨难。
2、关系表的不灵活性
关系表具有条理性,条理性是好的——但是,它使得程序员不得不编造或硬塞一些数据到已经定义好模式的列中。NoSQL开始越来越受到欢迎的原因之一,就是它为程序员提供了足够的灵活性,来加速数据库的使用。如果一个街道地址需要增加一行,那么,你可以将它很容易地插入到一个NoSQL文档中。如果你想添加一个完整的新的数据块,无论它包含什么内容,文档模型也可以原封不动地接受你的数据,而不必改为它要求的数据格式。
试想一下,你用整数格式建立了一个全部是邮编的表格。这个表是十分高效的,它执行的规则也很好。突然一次,有人上传了一个使用了连字符的九位数邮编。或者还有可能,你得到了一位来自加拿大客户的信件,上面写有邮政编码。
这时,一切都乱了。老板要求网站要在几小时内恢复正常工作。然而,现在已经没有时间来重建数据库。程序员可以做什么?也许,可以使用黑客手段把加拿大邮政编码由base64的数字格式改为base 10格式?或者设置一个使用转义编码的辅助表格,用来说明真正的邮政编码或者其他?谁知道呢?到处都有黑客,他们都是危险的。但你没有时间来搞定它。
MySQL的关联规则让每个人都诚实和谨慎,但它能强制我们避开易受攻击和欺骗的麻烦。
3、存储引擎混乱
总体来说,Mysql的存储引擎接口定义还算良好的。MySQL不是实际上的同一的数据库。它是由几个数据库组成,它们的大多数细节都被统一的表面掩盖了。开始时有一个MyISAM引擎,它很快但在前后一致上不能做到完备。有时你需要速度并且可以接受不一致的结果时是很好的。
当人们需要更多时,具备完整事务支持的Inno DB出现了。但这还不够。现在,它可能有20种存储引擎的选择——这足以使一个数据库管理员疯狂。当然,有时在不同的存储引擎之间切换而不必重写你的SQL是很好的,但是切换后总会带来混乱。这个表格我选择的引擎是MyISAM还是innoDB呢?或者,我决定输出的数据是CSV格式的吗?
4、JOIN联合查询
曾经,将数据分表保存是计算机科学史上的伟大创新。分开后的表不仅结构简单,使用上也简化了许多。但它却需要使用join语句来进行查询。
sql通过一系列join构建的复杂查询将开发者推入了困惑与绝望的深渊。而且存储引擎也需要以最优的方式来高效地解析join语句。开发者需要绞尽脑汁编写查询语句,然后数据库对其进行解析。
这就是很多注重运行速度的开发者放弃数据分表转而使用不规范数据表的原因。不区分数据实体,将所有数据保存到一个大表中——以避免复杂的查询。这样确实很快,并且服务器也不会耗尽内存。
现在的磁盘空间很廉价。8TB的磁盘已经在售,更大容量的也将上市。我们不再需要为使用join而绞尽脑汁了。
5、分支的混乱
毋庸置疑,一个可靠的、得到良好支持的MySQL分支,可以带来竞争和选择,但是它也引起困惑和混乱。更糟糕的是,一个称为MariaDB的MySQL分支,由Monty Widenius维护着。他同样也在参与编写MySQL。那么,Maria DB是真正独立的值得我们拥护的吗?或者它是MySQL?我们是否应该坚持使用由创建原始mysql数据库的组织运营的核心代码?或者我们应该加入那些被认为更聪明的,往往很酷的背叛者?
如何获取关于兼容性的信息?虽然Maria DB和MySQL十分相似,但它们之间也有差异。这就是大家一直都在争论它的原因。在性能方面,在我们查询的范围内,在两个阵营中,也许它们的工作方式相同,但也许不同,也许将来会不同。
6、开发MySQL的动机
虽然MySQL是一款成功的开源产品,但它仍属于商业中的一款产品,专业开发者需要靠它来获得利益,当然,最直接的利益就是薪资。当大多数用户在持续地享受开源许可证带来的最佳体验时,毫无疑问这家公司还在为赚取足够的钱来维持运营而努力。这导致自由代码在“社区版”和出售给企业的完整产品之间产生了奇怪的分岐。
我们应该对这款产品付钱吗?这种在社区版开展经营的行为是否公平?企业版中额外的功能是不是一个噱头,以引诱我们不断付费的呢?这至少说明一点,它是另一些需要回答的问题:选用哪个版本?遵照哪种许可证?选用它的哪个功能集?
7、原生JSON支持的缺乏
通过安装MySQL查看其年龄,然后你就知道需要添加哪些驱动程序使它变得可用。MySQL通常在3306端口上通信,一般输出的是它本身难以理解的格式化数据。如果要让你的代码和它通信,你必须添加另一层代码,将MySQL的语言转换成有用的东西。这些层的代码,以库的形式分发,经常需要人们购买一个商业许可证。
现代数据存储层通常直接以JSON通信。虽然MySQL和Maria DB现在有能力解析SQL中的JSON部分,但这还远远不够,原生的JSON接口已经被广泛使用于CouchDB、MongoDB,或任何最新的工具中。
8、封闭源和专有模块的兴起
虽然MySQL是开源的,但除了一些在”开源核心“周边开发的一些较新的、非开源的代码和专有模块。程序员也需要赚钱、需要生活,Oracle需要拿它的辛苦成果来换钱,这是一种现实,也是商业的性质。使用MySQL你也不可以免费得到任何东西。
要求MySQL始终坚持在一个很高的标准上,这有点不公平,因为开源的成功可能是一个圈套。它开始可以免费,但并不意味着它可以始终免费。如果企业需要更多新的功能,他们就要通过各种方式付费来获取。有时向Oracle付费,比自己来编写代码要便宜得多。有时商业的、不开源的代码是有意义的。
MySQL虽然作为一个成功的开源系统,但以上这些问题也总不可避免地出现,这就需要我们在它们发生之前有个深刻的认识,才能在今后的应用中避免不必要的麻烦。
在此我向大家推荐一个架构学习交流群。交流学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
五、MySQL分布式集群搭建
1 准备集群搭建环境
使用6台虚拟机来搭建MYSQL集群,相应的实验环境与对应的MYSQL节点之间的对应关系如下图所示:
管理节点(MGM):这类节点的作用是管理MySQLCluster内的其他节点,如提供配置数据,并停止节点,运行备份等。由于这类节点负责管理其他节点的配置,应该在启动其他节点之前启动这类节点。MGM节点是用命令“ndb_mgmd”启动的;
数据节点(NDB):这类节点用于保存Cluster的数据,数据节点的数目与副本的数目相关,是片段的倍数。例如,对于两个副本,每个副本有两个片段,那么就有4个数据节点,没有必要设定过多的副本,在NDB中数据会尽量的保存在内存中。数据节点使用命令“ndb”启动的;
SQL节点:这是用来访问Cluster数据的节点,对于MySQL Cluster,客户端节点是使用NDB Cluster存储引擎的传统MySQL服务器。通常,SQL节点使用命令“mysqld-ndbcluster”启动的;
2、准备安装包
在官网上下载mysql的安装包: mysql-cluster-gpl-7.4.11-Linux-glibc2.5-x86_64.tar.gz,并进行解压。
3、集群搭建流程
1]将上述安装包解压出来的文件都移到/usr/local/mysql下;
2]运行script目录下的mysql-install-db.sh脚本,运行命令为./mysql-install-db.sh --user=root--basedir =/usr/local/mysql --datadir=/usr/local/mysql;注意其中用户为root的名称需要跟配置文件my.cnf中的相同;
在管理节点,数据节点,SQL节点上都执行上述安装命令,从而完成对mysql的安装;
4、集群配置与启动
1]在管理节点上需要完成对于集群整体的配置配置:在/var/lib/mysql-cluster/config.ini中实现如下的配置信息:
2]在数据节点中需要在my.cnf中完成对于数据节点的相关配置信息,如下:
需要指明配置的数据节点的根目录,数据目录,socket连接配置,用户配置,以及对应的管理节点的ip地址配置;将配置完成的配置文件移动到/etc/my.cnf,完成;
3]在SQL节点上完成对于SQL节点的配置信息,同样的是在my.cnf中完成相应配置信息,并将配置文件移动到/etc/my.cnf中,相应的配置信息的设定如下所示:
完成以上配置后,就可以启动集群中的各个节点了。
5、集群启动
在启动mysql集群的时候,注意首先要启动管理节点,并依次启动其他等若干个节点,相应的启动步骤如下:
1]在管理节点上,切换到/usr/local/mysql/bin目录下,执行ndb_mgmd -f /var/lib/mysql-cluster/config.ini命令,完成管理节点的启动;
2]在各个数据节点上,切换到/usr/local/mysql/bin目录下,执行ndbd --initial(第一次启动时,否则执行ndbd即可),完成对数据节点的启动;
3]在各个SQL节点上,同样切换到/usr/local/mysql/bin目录下,执行mysqld_safe --user=root完成启动;
4]在管理节点上运行ndb_mgm命令,进入数据库管理的客户端,输入show命令,查看与之相连接的各个节点的状态;
5]在SQL节点上分别进入系统的安全状态,并完成对root用户的密码修改,运行以下指令,进行密码修改:
A use mysql,切换到mysql数据库;
B UPDATE user SET Password = PASSWORD('123456')WHERE user = 'root';从而实现对root密码的修改;
C flush privilege,完成修改;
6]修改使得任意主机都能连得上mysql,进行如下修改,同样安装第5步进入安全模式,并完成相应的修改,如下:
grant all on‘*.*’to ‘root@'%' identified by '123456';
这样就可以使得任意一个主机都可以通过root用户来登录mysql了;
6、集群测试
在集群上的一个SQL节点上执行创建数据库,并创建一张表,并完成相应的数据插入,如下:
A create database ctest; //创建数据库
B create table test(
id int primarykey; //创建一张表
);
C insert into test (id)values(1); //完成数据插入
登录另外一个SQL节点,并执行SQL查询操作,看数据库中是否已经有数据,如下:
select * from ctest;
如果有数据,表示数据插入成功;
7、关闭集群
1]首先关闭管理节点和数据节点,需要在管理节点上执行命令,如下:./ndb_mgm -e shutdown;
2]然后关闭SQL节点,在SQL节点上执行命令/usr/local/mysql/support-fies/mysql.server stop(其中/usr/local/mysql/是mysql的安装目录).从而关闭SQL节点
在此我向大家推荐一个架构学习交流群。交流学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
六、MySQL 的最佳实践
数据库操作是当今 Web 应用程序中的主要瓶颈。 不仅是 DBA(数据库管理员)需要为各种性能问题操心,程序员为做出准确的结构化表,优化查询性能和编写更优代码,也要费尽心思。 在本文中,我列出了一些针对程序员的 MySQL 优化技术。
在我们开始学习之前,我补充一点:你可以在 Envato Market 上找到大量的 MySQL 脚本和实用程序。
1.优化查询的查询缓存
大部分MySQL服务器都有查询缓存功能。这是提高性能的最有效的方法之一,这是由数据库引擎私下处理的。当同一个查询被多次执行,结果会直接从缓存里提取,这样速度就很快。
主要的问题是,这对程序员来说太简单了,不容易看到,我们很多人都容易忽略。我们实际上是可以组织查询缓存执行任务的。
查询缓存在第一行不执行的原因在于CURDTE()功能的使用。这适用于所有的非确定性功能,就像NOW()和RAND()等等。。。因为功能返回的结果是可变的。MySQL决定禁用查询器的查询缓存。我们所需要做的是通过添加一额外一行PHP,在查询前阻止它发生。
2. EXPLAIN你的选择查询
使用EXPLAIN关键词可以帮助了解MySQL是怎样运行你的查询的。这有助于发现瓶颈和查询或表结构的其它问题。
EXPLAIN的查询结果会展示哪一个索引被使用过,表示怎样扫描和储存的,等等。。。
选择一个SELECT查询(一个有连接的复杂查询会更好),在它的前面添加关键词EXPLAIN,这样就可以直接使用数据库了。结果会以一个漂亮的表来展示。例如,就好比我执行连接时忘了添加一栏的索引:
现在它只会从表2里面扫描9和16行,而非扫描7883行。经验法则是乘以所有“行”那一栏的数字,你的查询性能会跟结果数字成比例的。
3. 获取唯一行时使用LIMIT 1
有时当你查表时,你已经知道你正在查找的结果只有一行。你可能正在获取唯一记录,或者你可能只是查询是否存在满足你的WHERE子句条件的记录。
在这种情况下,将LIMIT 1添加到查询条件中可以提高性能。这样,数据库引擎将在找到刚刚第一个记录之后停止扫描记录,而不是遍历整个表或索引。
4. 索引搜索字段
索引不仅仅是为了主键或唯一键。如果你会在你的表中按照任何列搜索,你就都应该索引它们。
正如你所看到的,这个规则也适用于如 “last_name LIKE ‘a%’”的部分字符串搜索。当从字符串的开头搜索时,MySQL就可以使用那一列的索引。
你也应该明白什么样搜索可以不使用有规律的索引。例如,当搜索一个单词时(例如,”WHERE post_content LIKE ‘%apple%’”),你将不会看到普通索引的好处。你最好使用 mysql 全文搜索或者构建你自己的索引解决方案。
5. 索引并对连接使用同样的字段类型
如果你的应用程序包含许多连接查询, 你需要确保连接的字段在两张表上都建立了索引。 这会影响MySQL如何内部优化连接操作。
此外,被连接的字段,需要使用同样类型。例如, 如果你使用一个DECIMAL字段, 连接另一张表的INT字段, MySQL将无法使用至少一个索引。 即使字符编码也需要使用相同的字符类型。
6. 不要ORDER BY RAND()
起初这是一个听起来挺酷的技巧, 让许多菜鸟程序员陷入了这个陷阱。但你可能不知道,一旦你开始在查询中使用它,你创建了非常可怕的查询瓶颈。
如果你真的需要对结果随机排序, 这有一个更好的方法。补充一些额外代码,你将可以防止当数据成指数级增长时造成的瓶颈。关键问题是,MySQL必须在排序之前对表中的每一行执行RAND()操作(这需要处理能力),并且仅仅给出一行。
所以挑选一个小于结果数的随机数,并将其用作LIMIT子句中的偏移量。
7. 避免使用SELECT *
从数据表中读取的数据越多,查询操作速度就越慢。它增加了磁盘操作所需的时间。此外,当数据库服务器与Web服务器分开时,由于必须在服务器之间传输数据,将会有更长的网络延迟。
这是一个好习惯:当你使用SELECT语句时总是指定你需要的列。
8. 几乎总是有一个id字段
在每个以id列为PRIMARY KEY的数据表中,优先选择AUTO_INCREMENT或者INT。 也可以优选使用UNSIGNED,因为该值不能为负的。
即使你拥有一个具有唯一用户名字段的用户表,也不要将其作为主键。 VARCHAR字段作为主键(检索)速度较慢。通过内部ID引用所有的用户数据,你的代码中将更加结构化。
有些后台操作是由MySQL引擎本身完成的,它在内部使用主键字段。当数据库设置越复杂(集群,分区等…),这就变得更加重要了。
这个规则的一个可能的例外是“关联表”,用于两个表之间的多对多类型的关联。例如,“posts_tags”表中包含两列:post_id,tag_id,用于保存表名为“post”和“tags”的两个表之间的关系。这些表可以具有包含两个id字段的PRIMARY键。
9. 相比VARCHAR优先使用ENUM
ENUM枚举类型是非常快速和紧凑的。在内部它们像TINYINT一样存储,但它们可以包含和显示字符串值。这使他们成为某些领域的完美候选。
如果有一个字段只包含几种不同的值,请使用ENUM而不是VARCHAR。例如,它可以是名为“status”的列,并且只包含诸如“active”,“inactive”,“pending”,“expired”等的值…
关于如何重构你的数据表,甚至有一种方法是可以从MySQL本身得到“建议”。 当你有一个VARCHAR字段,它实际上建议你将该列类型更改为ENUM。这通过调用PROCEDURE ANALYZE()来完成。
在此我向大家推荐一个架构学习交流群。交流学习群号:575745314 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
10. 使用PROCEDURE ANALYSE()获取建议
PROCEDURE ANALYSE() 将使用MySQL分析列结构和表中的实际数据,为你提供一些建议。它只有在数据表中有实际数据时才有用,因为这在分析决策时很重要。
例如,如果你创建了一个INT类型的主键,但没有太多行,MySQL则可能建议您改用MEDIUMINT。或者如果你使用VARCHAR字段,如果表里只有很少的取值,你可能会得到一个建议是将其转换为ENUM。
你也可以在其中一个表视图中单击phpmyadmin中的“建议表结构”链接来执行此操作。
请记住,这些只是建议。 如果你的数据表变得越来越大,他们甚至可能不是正确的建议。至于如何修改最终是你来决定。
11. 如果可以的话使用NOT NULL
除非你有非常重要的理由使用NULL值,否则你应该设置你的列为NOT NULL。
首先,问一下你自己在空字符串值和NULL值之间(对应INT字段:0 vs. NULL)是否有任何的不同.如果没有理由一起使用这两个,那么你就不需要一个NULL字段(你知道在Oracle中NULL和空字符串是一样的吗?)。
NULL列需要额外的空间,他们增加了你的比较语句的复杂度。如果可以的话尽量避免它们。当然,我理解一些人,他们也许有非常重要的理由使用NULL值,这不总是一件坏事。
摘自MySQL 文档:
“行空列需要额外的空间来记录它们的值是否为空。 对于MyISAM表,每个NULL列需要一点额外的,围捕到最近的字节”。
12. 预处理语句
使用预处理语句有诸多好处,包括更高的性能和更好的安全性。
预处理语句默认情况下会过滤绑定到它的变量,这对于避免SQL注入攻击极为有效。当然你也可以指定要过滤的变量。但这些方法更容易出现人为错误,也更容易被程序员遗忘。这在使用框架或 ORM 的时候会出现一些问题。
既然我们关注性能,那就应该说说这个方面的好处。当在应用中多次使用同一个查询的时候,它的好处特别明显。既然向同一个预备好的语句中传入不同的参数值,MySQL 对这个语句也只会进行一次解析。
同时,最新版本的 MySQL 在传输预备好的语句时会采用二进制形式,这样做的作用非常明显,而且对减少网络延迟很有帮助。
曾经有一段时间,许多程序员为了一个重要的原因则避免使用预处理语句。这个原因就是,它们不会被MySQL 缓存。不过在 5.1 版本的某个时候,查询缓存也得到的支持。
想在 PHP 中使用预处理语句,你可以看看 mysqli 扩展 或使用数据抽象层,如 PDO。
13. 无缓冲查询
通常当你从脚本执行一个查询,在它可以继续后面的任务之前将需要等待查询执行完成。你可以使用无缓冲的查询来改变这一情况。
在PHP 文档中对 mysql_unbuffered_query() f函数有一个很好的解释:
“mysql_unbuffered_query()发送SQL查询查询MySQL没有自动抓取和缓冲结果行mysql_query()。 这节省了大量的内存生产大型结果集的SQL查询,你可以在结果集后立即开始工作第一行被检索到的是你不必等到完整的SQL查询已经完成。”
然而,它有一定的局限性。你必须在执行另一个查询之前读取所有的行或调用mysql_free_result() 。另外你不能在结果集上使用mysql_num_rows() 或 mysql_data_seek() 。
14. 使用 UNSIGNED INT 存储IP地址
很多程序员没有意识到可以使用整数类型的字段来存储 IP 地址,所以一直使用 VARCHAR(15) 类型的字段。使用 INT 只需要 4 个字节的空间,而且字段长度固定。
必须确保列是 UNSINGED INT 类型,因为 IP 地址可能会用到 32 位无符号整型数据的每一个位。
在查询中可以使用 INET_ATON() 来把一个IP转换为整数,用 INET_NTOA() 来进行相反的操作。在 PHP 也有类似的函数,ip2long() 和 long2ip()。
15. 固定长度(静态)的表会更快
(译者注:这里提到的表的长度,实际是指表头的长度,即表中每条数据占用的空间大小,而不是指表的数据量)
如果表中所有列都是“固定长度”,那么这个表被认为是“静态”或“固定长度”的。不固定的列类型包括 VARCHAR、TEXT、BLOB等。即使表中只包含一个这些类型的列,这个表就不再是固定长度的,MySQL 引擎会以不同的方式来处理它。
固定长度的表会提高性能,因为 MySQL 引擎在记录中检索的时候速度会更快。如果想读取表中的某一地,它可以直接计算出这一行的位置。如果行的大小不固定,那就需要在主键中进行检索。
它们也易于缓存,崩溃后容易重建。不过它们也会占用更多空间。例如,如果你把一个 VARCHAR(20) 的字符改为 CHAR(20) 类型,它会总是占用 20 个字节,不管里面存的是什么内容。
你可以使用“垂直分区”技术,将长度变化的列拆分到另一张表中。来看看:
16. 垂直分区
垂直分区是为了优化表结构而对其进行纵向拆分的行为。
示例 1: 你可能会有一张用户表,包含家庭住址,而这个不是一个常用数据。这时候你可以选择把表拆分开,将住址信息保存到另一个表中。这样你的主用户表就会更小。如你所知,表越小越快。
示例 2: 表中有一个 “last_login” 字段,用户每次登录网站都会更新这个字段,而每次更新都会导致这个表缓存的查询数据被清空。这种情况下你可以将那个字段放到另一张表里,保持用户表更新量最小。
不过你也需要确保不会经常联合查询分开后的两张表,要不然你就得忍受由这带来的性能下降。
17. 拆分大型DELETE或INSERT语句
如果你需要在网站上执行大型DELETE或INSERT查询,则需要注意不要影响网络流量。当执行大型语句时,它会锁表并使你的Web应用程序停止。
Apache运行许多并行进程/线程。 因此它执行脚本效率很高。所以服务器不期望打开过多的连接和进程,这很消耗资源,特别是内存。
如果你锁表很长时间(如30秒或更长),在一个高流量的网站,会导致进程和查询堆积,处理这些进程和查询可能需要很长时间,最终甚至使你的网站崩溃。
如果你的维护脚本需要删除大量的行,只需使用LIMIT子句,以避免阻塞。
18.越少的列越快
对于数据库引擎,磁盘可能是最重要的瓶颈。更小更紧凑的数据、减少磁盘传输量,通常有助于性能提高。
MySQL文档Storage Requirements 有所有数据类型清单。
如果已知表具有很少的行,则没有理由是主键类型为INT,可以用MEDIUMINT、SMALLINT代替,甚至在某些情况下使用TINYINT。 如果不需要完整时间记录,请使用DATE而不是DATETIME。
确保留下合理的扩展空间,不然你可能会像Slashdot这样。
19. 选择正确的存储引擎
MySQL有两个主要存储引擎,MyISAM和InnoDB。 每个都有自己的优点和缺点。
MyISAM适用于读取繁重的应用程序,但是当有很多写入时它不能很好地扩展。 即使你正在更新一行的一个字段,整个表也被锁定,并且在语句执行完成之前,其他进程甚至无法读取该字段。 MyISAM在计算SELECT COUNT(*)的查询时非常快。
InnoDB是一个更复杂的存储引擎,对于大多数小的应用程序,它比MyISAM慢。 但它支持基于行的锁定,使其更好地扩展。 它还支持一些更高级的功能,比如事务。
● MyISAM存储引擎
● InnoDB存储引擎
20. 使用对象关系映射器(ORM, Object Relational Mapper)
通过使用ORM(对象关系映射器),你可以获得一定的性能提升。ORM可以完成的一切事情,手动编码也可完成。但这可能意味着需要太多额外的工作,并且需要高水平的专业知识。
ORM以“延迟加载”著称。这意味着它们仅在需要时获取实际值。但是你需要小心处理他们,否则你可能最终创建了许多微型查询,这会降低数据库性能。
ORM还可以将多个查询批处理到事务中,其操作速度比向数据库发送单个查询快得多。
目前我最喜欢的PHP-ORM是Doctrine。我写了一篇关于如何安装Doctrine与CodeIgniter的文章(install Doctrine with CodeIgniter)。
21. 小心使用持久连接
持久连接意味着减少重建连接到MySQL的成本。 当持久连接被创建时,它将保持打开状态直到脚本完成运行。 因为Apache重用它的子进程,下一次进程运行一个新的脚本时,它将重用相同的MySQL连接。
理论上看起来不错。 但从我个人(和许多其他人)的经验看来,这个功能可能会导致更多麻烦。 你可能会出现连接数限制问题、内存问题等等。
Apache总是并行运行的,它创建许多子进程。 这是持久连接在这种环境中不能很好工作的主要原因。 在你考虑使用mysql_pconnect()之前,请咨询你的系统管理员。