MSN/Skype/Gmail/AIM: hideto.bj@gmail.com
RSS地址:
http://hideto.javaeye.com/rss共有9篇文章被收藏推荐
收录于2008-01-03
认领
报错
推荐
13
最新文章
精华文章
13位订阅者
作者: hideto
链接:http://hideto.javaeye.com/blog/271004
发表时间: 2008年11月19日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
终于搞明白堆排序了,汗一个
先上代码:
...
作者: hideto 链接:http://hideto.javaeye.com/blog/271004 发表时间: 2008年11月19日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
终于搞明白堆排序了,汗一个
先上代码:
算法原理:
利用二叉树,先将一个数组构建成一个“最大堆”,保证对每个节点i,它的相邻子节点left和right都<=i
这时根节点就是最大的数,将它和最后一个节点互换位置
然后从根节点开始与相邻的子节点比较大小,如果left或right比它大,则互换位置,称为“下移”,直到第n-1个节点,这一轮“下移”之后根节点成为除了最后一个节点之外最大的数,将它和倒数第二个节点互换位置
。。。
循环直到所有节点做完“下移”操作,这时数组已经从小到大排好序了
关键:
有两点:
1,先构建“最大堆”,从最后一个节点的父节点开始做“下移”,直到根节点
2,每次“下移”结束后不能将最大值根节点从数组中删除,只能跟最后一个节点互换位置,这样是为了保证二叉树的结构不变,即还是一个“最大堆”,所以堆排序又称为“in place sort”
时间复杂度:
一个长度为n的数组,用二叉树来表示的话共有lgn层
对节点i,比较它相邻的left节点和right节点并做“下移”操作的时间为Θ(1)
可以用数学归纳法来证明heapsort的时间复杂度为Θ(nlogn)
1,初始化构建“最大堆”的时间为O(nlgn),不影响结果(实际上为O(n))
2,可以知道对n=3,6,f(n) < nlgn,
而f(2n) = f(n) + nlg(2n)
< nlgn + n(1+lgn)
= 2nlgn + n
< 2n(lgn + 1)
= 2nlg2n
所以fn = Θ(nlgn)
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
作者: hideto 链接:http://hideto.javaeye.com/blog/271004 发表时间: 2008年11月19日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
终于搞明白堆排序了,汗一个
先上代码:
def heapify(a, idx, size)
left_idx = 2 * idx + 1
right_idx = 2 * idx + 2
bigger_idx = idx
bigger_idx = left_idx if left_idx < size && a[left_idx] > a[idx]
bigger_idx = right_idx if right_idx < size && a[right_idx] > a[bigger_idx]
if bigger_idx != idx
a[idx], a[bigger_idx] = a[bigger_idx], a[idx]
heapify(a, bigger_idx, size)
end
end
def build_heap(a)
last_parent_idx = a.length / 2 - 1
i = last_parent_idx
while i >= 0
heapify(a, i, a.size)
i = i - 1
end
end
def heap_sort(a)
return a if a.size <= 1
size = a.size
build_heap(a)
while size > 0
a[0], a[size-1] = a[size-1], a[0]
size = size - 1
heapify(a, 0, size)
end
return a
end
a = [1,5,3,6,4,3,2,7,9,0,8,0,10]
p heap_sort(a)
算法原理:
利用二叉树,先将一个数组构建成一个“最大堆”,保证对每个节点i,它的相邻子节点left和right都<=i
这时根节点就是最大的数,将它和最后一个节点互换位置
然后从根节点开始与相邻的子节点比较大小,如果left或right比它大,则互换位置,称为“下移”,直到第n-1个节点,这一轮“下移”之后根节点成为除了最后一个节点之外最大的数,将它和倒数第二个节点互换位置
。。。
循环直到所有节点做完“下移”操作,这时数组已经从小到大排好序了
关键:
有两点:
1,先构建“最大堆”,从最后一个节点的父节点开始做“下移”,直到根节点
2,每次“下移”结束后不能将最大值根节点从数组中删除,只能跟最后一个节点互换位置,这样是为了保证二叉树的结构不变,即还是一个“最大堆”,所以堆排序又称为“in place sort”
时间复杂度:
一个长度为n的数组,用二叉树来表示的话共有lgn层
对节点i,比较它相邻的left节点和right节点并做“下移”操作的时间为Θ(1)
可以用数学归纳法来证明heapsort的时间复杂度为Θ(nlogn)
1,初始化构建“最大堆”的时间为O(nlgn),不影响结果(实际上为O(n))
2,可以知道对n=3,6,f(n) < nlgn,
而f(2n) = f(n) + nlg(2n)
< nlgn + n(1+lgn)
= 2nlgn + n
< 2n(lgn + 1)
= 2nlg2n
所以fn = Θ(nlgn)
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
- 加入阿里巴巴,发展潜力无限
- 你想过自己的博客制作成书吗 - JavaEye推出博客自动生成电子书功能!
- 搜狐网站诚聘Java、PHP和C++工程师
- Windows7在微软WinHEC 2008上揭开神秘面纱
作者: hideto
链接:http://hideto.javaeye.com/blog/267093
发表时间: 2008年11月14日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
...
作者: hideto 链接:http://hideto.javaeye.com/blog/267093 发表时间: 2008年11月14日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
一个并发程序是由在时间上重叠的一组逻辑流组成的
三种不同的构建并发程序的机制:进程、I/O多路复用和线程
进程是由内核自动调度的,而且因为它们有各自独立的虚拟地址空间,所以要实现共享数据,它们需要显示的IPC机制
事件驱动程序创建它们自己的并发逻辑流,这些逻辑流被模型化为状态机,用I/O多路复用来显示地调度这些流
因为程序运行在一个单一进程中,所以在流之间共享数据速度很快而且很容易
线程是这些方法的综合,同基于进程的流一样,线程是由内核自动调度的
线程运行在一个单一进程的上下文中,因此可以快速而方便地共享数据
无论哪种并发机制,同步对共享数据的并发访问都是一个困难的问题
提出对信号量的P和V操作就是为了帮助解决这个问题
信号量操作可以用来提供对共享数据的互斥访问,也对诸如生产者-消费者程序中共享缓冲区这样的资源访问进行调度
一个函数被称为线程安全的,当且仅当被多个并发线程反复地调用时,它会一直产生正确的结果
四类线程不安全函数:
1,不保护共享变量的函数
2,保持跨越多个调用的状态的函数
3,返回指向静态变量的指针的函数
4,调用线程不安全函数的函数
可重入函数:当它们被多个线程调用时,不会引用任何共享数据
竞争和死锁是并发程序中出现的另一些困难的问题
当程序员错误地假设逻辑流该如何调度时,就会发生竞争
当一个流等待一个永远不会发生的事件时,就会产生死锁
互斥锁加锁顺序规则:如果对于程序中每对互斥锁(s,t),每个既包含s也包含t的线程都按照相同的顺序同时对它们加锁,那么这个程序就是无死锁的
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
作者: hideto 链接:http://hideto.javaeye.com/blog/267093 发表时间: 2008年11月14日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
一个并发程序是由在时间上重叠的一组逻辑流组成的
三种不同的构建并发程序的机制:进程、I/O多路复用和线程
进程是由内核自动调度的,而且因为它们有各自独立的虚拟地址空间,所以要实现共享数据,它们需要显示的IPC机制
事件驱动程序创建它们自己的并发逻辑流,这些逻辑流被模型化为状态机,用I/O多路复用来显示地调度这些流
因为程序运行在一个单一进程中,所以在流之间共享数据速度很快而且很容易
线程是这些方法的综合,同基于进程的流一样,线程是由内核自动调度的
线程运行在一个单一进程的上下文中,因此可以快速而方便地共享数据
无论哪种并发机制,同步对共享数据的并发访问都是一个困难的问题
提出对信号量的P和V操作就是为了帮助解决这个问题
信号量操作可以用来提供对共享数据的互斥访问,也对诸如生产者-消费者程序中共享缓冲区这样的资源访问进行调度
一个函数被称为线程安全的,当且仅当被多个并发线程反复地调用时,它会一直产生正确的结果
四类线程不安全函数:
1,不保护共享变量的函数
2,保持跨越多个调用的状态的函数
3,返回指向静态变量的指针的函数
4,调用线程不安全函数的函数
可重入函数:当它们被多个线程调用时,不会引用任何共享数据
竞争和死锁是并发程序中出现的另一些困难的问题
当程序员错误地假设逻辑流该如何调度时,就会发生竞争
当一个流等待一个永远不会发生的事件时,就会产生死锁
互斥锁加锁顺序规则:如果对于程序中每对互斥锁(s,t),每个既包含s也包含t的线程都按照相同的顺序同时对它们加锁,那么这个程序就是无死锁的
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
- 搜狐网站诚聘Java、PHP和C++工程师
- 加入阿里巴巴,发展潜力无限
- Windows7在微软WinHEC 2008上揭开神秘面纱
- 你想过自己的博客制作成书吗 - JavaEye推出博客自动生成电子书功能!
作者: hideto
链接:http://hideto.javaeye.com/blog/266582
发表时间: 2008年11月13日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
虚拟存储器是对主存的一个抽象...
作者: hideto 链接:http://hideto.javaeye.com/blog/266582 发表时间: 2008年11月13日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
虚拟存储器是对主存的一个抽象
支持虚拟存储器的处理器通过使用一种叫虚拟寻址的间接形式来使用主存
处理器产生一个虚拟地址,在被发送到主存之前,这个地址被翻译成一个物理地址
从虚拟地址空间到物理地址空间的地址翻译要求硬件和软件紧密合作
专门的硬件通过使用页表来翻译虚拟地址,而页表的内容是由操作系统提供的
虚拟存储器的三个重要功能:
1,它在主存中自动缓存最近使用的存放磁盘上的虚拟地址空间的内容
虚拟存储器缓存中的块叫做页。对磁盘上页的引用会触发缺页,缺页将控制转移到操作系统中的一个缺页处理程序
缺页处理程序将页面从磁盘拷贝到主存缓存,如果必要,将写回被驱逐的页
2,虚拟存储器简化了存储器管理,进而又简化了链接、在进程间共享数据、进程的存储器分配、以及程序加载
3,虚拟存储器通过在每条页表条目中加入保护位,从而简化了存储器保护
地址翻译的过程必须和系统中任意硬件缓存的操作集成在一起
大多数页表条目位于L1高速缓存中,但是一个称为TLB的页表条目在芯片上的高速缓存,通常会消除访问在L1上的页表条目的开销
现代系统通过将虚拟存储器组块和磁盘上的文件组块关联起来,来初始化虚拟存储器组块,这个过程称为存储器映射
存储器映射为共享数据、创建新的进程以及加载程序,提供了一种高效的机制
应用可以使用mmap函数来手工地创建和删除虚拟地址空间的区域
然而大多数程序依赖于动态存储器分配器,如malloc,它管理虚拟地址空间区域内的一个称为堆的区域
动态存储器分配器是一个有系统级感觉的应用级程序,它直接操作存储器,而无需类型系统的很多帮助
分配器有两种类型:显示分配器要求应用显式地释放它们的存储器块:隐式分配器(垃圾收集器)自动释放任何无用的和不可达的块
对于C程序员来说,管理和使用虚拟存储器是一件困难和容易出错的任务
常见的错误示例包括:间接引用坏指针,读取未初始化的存储器,允许栈缓冲区溢出,假设指针和它们指向的对象大小相同,
引用指针而不是它所指向的对象,误解指针运算,引用不存在的变量,以及引起存储器泄漏
垃圾收集可以追溯到John McCarthy在20世纪60年代早期在MIT开发的Lisp系统
McCarthy独创的Mark&Sweep(标记&清除)算法可以建立在已存在的malloc包的基础之上,为C和C++程序提供垃圾收集
垃圾收集器将存储器视为一张有向可达图,该图的节点被分成一组根节点和一组堆节点
每个堆节点对应于堆中的一个已分配块,有向边p->q意味着块p中的某个位置指向块q中的某个位置
根节点对应于不在堆中的位置,它们中包含着指向堆中的指针
这些位置可以是寄存器、栈里的变量或者是虚拟存储器中读写数据区域内的全局变量
当存在一条从任意根节点出发并到达p的有向路径时,我们说一个节点p是可达的
在任何时刻,和垃圾对应的不可达节点是不能被应用再次使用的
垃圾收集器的角色是维护可达图的某种表示,并通过释放不可达节点并将它们返回给空闲链表,来定期地回收它们
ML和Java这样的语言的垃圾收集器对应用如何创建和使用指针有很严格的控制,能够维护可达图的一种精确的表示,因此也就能够回收所有垃圾
而诸如C和C++这样的语言的收集器通常不能维持可达图的精确表示,这样的收集器也叫保守的垃圾收集器
收集器可以按需提供它们的服务,或者它们可以作为一个和应用并行的独立线程,不断地更新可达图和回收垃圾
Mark&Sweep垃圾收集器由标记阶段和清除阶段组成
标记阶段标记出根节点的所有可达的和已分配的后继,而后面的清除阶段释放每个未被标记的已分配块
典型地,块头部中空闲的低位中的一位用来表示这个块是否被标记了
C程序的Mark&Sweep收集器必须是保守的,其根本原因是C语言不会用类型信息来标记存储器位置
因此,像int或者float这样的标量可以伪装成指针
例如,假设某个可达的已分配块在它的有效载荷中包含一个int,其值碰巧对应于某个其他已分配块b的有效载荷中的一个地址
对收集器而言,是没有办法推断出这个数据实际是int而不是指针
因此,分配器必须保守地将块b标记为可达,尽管事实上它可能是不可达的
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
作者: hideto 链接:http://hideto.javaeye.com/blog/266582 发表时间: 2008年11月13日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
虚拟存储器是对主存的一个抽象
支持虚拟存储器的处理器通过使用一种叫虚拟寻址的间接形式来使用主存
处理器产生一个虚拟地址,在被发送到主存之前,这个地址被翻译成一个物理地址
从虚拟地址空间到物理地址空间的地址翻译要求硬件和软件紧密合作
专门的硬件通过使用页表来翻译虚拟地址,而页表的内容是由操作系统提供的
虚拟存储器的三个重要功能:
1,它在主存中自动缓存最近使用的存放磁盘上的虚拟地址空间的内容
虚拟存储器缓存中的块叫做页。对磁盘上页的引用会触发缺页,缺页将控制转移到操作系统中的一个缺页处理程序
缺页处理程序将页面从磁盘拷贝到主存缓存,如果必要,将写回被驱逐的页
2,虚拟存储器简化了存储器管理,进而又简化了链接、在进程间共享数据、进程的存储器分配、以及程序加载
3,虚拟存储器通过在每条页表条目中加入保护位,从而简化了存储器保护
地址翻译的过程必须和系统中任意硬件缓存的操作集成在一起
大多数页表条目位于L1高速缓存中,但是一个称为TLB的页表条目在芯片上的高速缓存,通常会消除访问在L1上的页表条目的开销
现代系统通过将虚拟存储器组块和磁盘上的文件组块关联起来,来初始化虚拟存储器组块,这个过程称为存储器映射
存储器映射为共享数据、创建新的进程以及加载程序,提供了一种高效的机制
应用可以使用mmap函数来手工地创建和删除虚拟地址空间的区域
然而大多数程序依赖于动态存储器分配器,如malloc,它管理虚拟地址空间区域内的一个称为堆的区域
动态存储器分配器是一个有系统级感觉的应用级程序,它直接操作存储器,而无需类型系统的很多帮助
分配器有两种类型:显示分配器要求应用显式地释放它们的存储器块:隐式分配器(垃圾收集器)自动释放任何无用的和不可达的块
对于C程序员来说,管理和使用虚拟存储器是一件困难和容易出错的任务
常见的错误示例包括:间接引用坏指针,读取未初始化的存储器,允许栈缓冲区溢出,假设指针和它们指向的对象大小相同,
引用指针而不是它所指向的对象,误解指针运算,引用不存在的变量,以及引起存储器泄漏
垃圾收集可以追溯到John McCarthy在20世纪60年代早期在MIT开发的Lisp系统
McCarthy独创的Mark&Sweep(标记&清除)算法可以建立在已存在的malloc包的基础之上,为C和C++程序提供垃圾收集
垃圾收集器将存储器视为一张有向可达图,该图的节点被分成一组根节点和一组堆节点
每个堆节点对应于堆中的一个已分配块,有向边p->q意味着块p中的某个位置指向块q中的某个位置
根节点对应于不在堆中的位置,它们中包含着指向堆中的指针
这些位置可以是寄存器、栈里的变量或者是虚拟存储器中读写数据区域内的全局变量
当存在一条从任意根节点出发并到达p的有向路径时,我们说一个节点p是可达的
在任何时刻,和垃圾对应的不可达节点是不能被应用再次使用的
垃圾收集器的角色是维护可达图的某种表示,并通过释放不可达节点并将它们返回给空闲链表,来定期地回收它们
ML和Java这样的语言的垃圾收集器对应用如何创建和使用指针有很严格的控制,能够维护可达图的一种精确的表示,因此也就能够回收所有垃圾
而诸如C和C++这样的语言的收集器通常不能维持可达图的精确表示,这样的收集器也叫保守的垃圾收集器
收集器可以按需提供它们的服务,或者它们可以作为一个和应用并行的独立线程,不断地更新可达图和回收垃圾
Mark&Sweep垃圾收集器由标记阶段和清除阶段组成
标记阶段标记出根节点的所有可达的和已分配的后继,而后面的清除阶段释放每个未被标记的已分配块
典型地,块头部中空闲的低位中的一位用来表示这个块是否被标记了
C程序的Mark&Sweep收集器必须是保守的,其根本原因是C语言不会用类型信息来标记存储器位置
因此,像int或者float这样的标量可以伪装成指针
例如,假设某个可达的已分配块在它的有效载荷中包含一个int,其值碰巧对应于某个其他已分配块b的有效载荷中的一个地址
对收集器而言,是没有办法推断出这个数据实际是int而不是指针
因此,分配器必须保守地将块b标记为可达,尽管事实上它可能是不可达的
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
- 搜狐网站诚聘Java、PHP和C++工程师
- 你想过自己的博客制作成书吗 - JavaEye推出博客自动生成电子书功能!
- Windows7在微软WinHEC 2008上揭开神秘面纱
- 加入阿里巴巴,发展潜力无限
作者: hideto
链接:http://hideto.javaeye.com/blog/263040
发表时间: 2008年11月06日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
详情请见:
http://ecug.org/
...
作者: hideto 链接:http://hideto.javaeye.com/blog/263040 发表时间: 2008年11月06日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
详情请见:
http://ecug.org/
大家也帮忙宣传宣传
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
作者: hideto 链接:http://hideto.javaeye.com/blog/263040 发表时间: 2008年11月06日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
详情请见:
http://ecug.org/
大家也帮忙宣传宣传
已有 0 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
- Windows7在微软WinHEC 2008上揭开神秘面纱
- 你想过自己的博客制作成书吗 - JavaEye推出博客自动生成电子书功能!
- 搜狐网站诚聘Java、PHP和C++工程师
- 加入阿里巴巴,发展潜力无限
作者: hideto
链接:http://hideto.javaeye.com/blog/259126
发表时间: 2008年10月28日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
MySQL 5.1参考手册 :: 7. 优化
一、查询优化...
作者: hideto 链接:http://hideto.javaeye.com/blog/259126 发表时间: 2008年10月28日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
MySQL 5.1参考手册 :: 7. 优化
一、查询优化
使用EXPLAIN
返回Field、Type、Null、Key、Default、Extra这几列对应的表中每个字段的值
相当于DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name
借助于EXPLAIN,可以知道什么时候必须为表加入索引以得到一个使用索引来寻找记录的更快的SELECT
EXPLAIN为用于SELECT语句中的每个表返回一行信息
EXPLAIN的每个输出行提供一个表的相关信息,并且每个行包括下面的列:
id
SELECT识别符。这是SELECT的查询序列号。
select_type
SELECT类型,可以为以下任何一种:
1, SIMPLE
简单SELECT(不使用UNION或子查询)
2, PRIMARY
最外面的SELECT
3, UNION
UNION中的第二个或后面的SELECT语句
4, DEPENDENT UNION
UNION中的第二个或后面的SELECT语句,取决于外面的查询
5, UNION RESULT
UNION的结果。
6, SUBQUERY
子查询中的第一个SELECT
7, DEPENDENT SUBQUERY
子查询中的第一个SELECT,取决于外面的查询
8, DERIVED
导出表的SELECT(FROM子句的子查询)
table
输出的行所引用的表。
type
联接类型。下面给出各种联接类型,按照从最佳类型到最坏类型进行排序:
1, system
表仅有一行(=系统表)。这是const联接类型的一个特例。
2, const
表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读
取一次!
3, eq_ref
对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并
且索引是UNIQUE或PRIMARY KEY。
4, ref
对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或
PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。
5, ref_or_null
该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。
6, index_merge
该联接类型表示使用了索引合并优化方法。
7, unique_subquery
该类型替换了下面形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
8, index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
9, range
只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL
。
10, index
该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。
11, ALL
对于每个来自于先前的表的行组合,进行完整的表扫描。
possible_keys
possible_keys列指出MySQL能使用哪个索引在该表中找到行。
如果该列是NULL,则没有相关的索引。
在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。
为了看清一张表有什么索引,使用SHOW INDEX FROM tbl_name。
key
key列显示MySQL实际决定使用的键(索引)。
如果没有选择索引,键是NULL。
要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
key_len
key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。
ref
ref列显示使用哪个列或常数与key一起从表中选择行。
rows
rows列显示MySQL认为它执行查询时必须检查的行数。
Extra
该列包含MySQL解决查询的详细信息。下面解释了该列可以显示的不同的文本字符串:
1, Distinct
MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。
2, Not exists
MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行。
3, range checked for each record(index map: #)
MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
4, Using filesort
MySQL需要额外的一次传递,以找出如何按排序顺序检索行。
5, Using index
从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。当查询只使用作为单一索引一部分的列时,可以使用该策略
。
6, Using temporary
为了解决查询,MySQL需要创建一个临时表来容纳结果。典型情况如查询包含可以按不同情况列出列的GROUP BY和ORDER BY子句时。
7, Using where
WHERE子句用于限制哪一个行匹配下一个表或发送到客户。
8, Using sort_union(...), Using union(...), Using intersect(...)
这些函数说明如何为index_merge联接类型合并索引扫描。
9, Using index for group-by
类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查询GROUP BY或DISTINCT查询的所有列,
而不要额外搜索硬盘访问实际的表。
MySQL优化器会对JOIN、INDEX、GROUP BY、ORDER BY做一些优化
二、MySQL锁
对WRITE,MySQL使用的表锁定方法原理如下
* 如果在表上没有锁,在它上面放一个写锁。
* 否则,把锁定请求放在写锁定队列中。
对READ,MySQL使用的锁定方法原理如下:
* 如果在表上没有写锁定,把一个读锁定放在它上面。
* 否则,把锁请求放在读锁定队列中。
可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:
三、数据库结构优化
1, 使数据尽可能小
尽可能地使用最有效(最小)的数据类型
尽可能使用较小的整数类型使表更小
如果可能,声明列为NOT NULL
对于MyISAM表,如果没有任何变长列(VARCHAR、TEXT或BLOB列),使用固定尺寸的记录格式
在MySQL/InnoDB中,InnoDB表使用更紧凑的存储格式
紧凑的InnoDB格式也改变了包含UTF-8数据的CHAR列的保存方式
每张表的主索引应该尽可能短
只创建你确实需要的索引
如果很可能一个索引在头几个字符上有唯一的前缀,仅仅索引该前缀比较好
使用列索引和多列索引
索引用于快速找出在某个列中有一特定值的行。
不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。
表越大,花费的时间越多。
如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据。
索引用于下面的操作:
1,快速找出匹配一个WHERE子句的行。
2,删除行。如果可以在多个索引中进行选择,MySQL通常使用找到最少行的索引。
3,当执行联接时,从其它表检索行。
4,对具体有索引的列key_col找出MAX()或MIN()值。由预处理器进行优化,检查是否对索引中在key_col之前发生所有关键字元素使用了WHERE
key_part_# = constant。
四、优化MySQL服务器
这个命令生成所有mysqld选项和可配置变量的列表:
如果有一个mysqld服务器正在运行,通过连接它并执行这个命令,可以看到实际上使用的变量的值:
还可以通过下面的语句看到运行服务器的统计和状态指标:
通常情况若给MySQL更多的内存性能会更好。
当调节MySQL服务器时,要配置的两个最重要的变量是key_buffer_size和table_cache:
不同的机器硬件上使用不同的编译器性能也会有不同的提高
已有 1 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
作者: hideto 链接:http://hideto.javaeye.com/blog/259126 发表时间: 2008年10月28日
声明:本文系JavaEye网站发布的原创博客文章,未经作者书面许可,严禁任何网站转载本文,否则必将追究法律责任!
MySQL 5.1参考手册 :: 7. 优化
一、查询优化
使用EXPLAIN
EXPLAIN tbl_name
返回Field、Type、Null、Key、Default、Extra这几列对应的表中每个字段的值
相当于DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name
EXPLAIN [EXTENDED] SELECT select_options
借助于EXPLAIN,可以知道什么时候必须为表加入索引以得到一个使用索引来寻找记录的更快的SELECT
EXPLAIN为用于SELECT语句中的每个表返回一行信息
EXPLAIN的每个输出行提供一个表的相关信息,并且每个行包括下面的列:
id
SELECT识别符。这是SELECT的查询序列号。
select_type
SELECT类型,可以为以下任何一种:
1, SIMPLE
简单SELECT(不使用UNION或子查询)
2, PRIMARY
最外面的SELECT
3, UNION
UNION中的第二个或后面的SELECT语句
4, DEPENDENT UNION
UNION中的第二个或后面的SELECT语句,取决于外面的查询
5, UNION RESULT
UNION的结果。
6, SUBQUERY
子查询中的第一个SELECT
7, DEPENDENT SUBQUERY
子查询中的第一个SELECT,取决于外面的查询
8, DERIVED
导出表的SELECT(FROM子句的子查询)
table
输出的行所引用的表。
type
联接类型。下面给出各种联接类型,按照从最佳类型到最坏类型进行排序:
1, system
表仅有一行(=系统表)。这是const联接类型的一个特例。
2, const
表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读
取一次!
3, eq_ref
对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并
且索引是UNIQUE或PRIMARY KEY。
4, ref
对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或
PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。
5, ref_or_null
该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。
6, index_merge
该联接类型表示使用了索引合并优化方法。
7, unique_subquery
该类型替换了下面形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
8, index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
9, range
只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL
。
10, index
该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。
11, ALL
对于每个来自于先前的表的行组合,进行完整的表扫描。
possible_keys
possible_keys列指出MySQL能使用哪个索引在该表中找到行。
如果该列是NULL,则没有相关的索引。
在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。
为了看清一张表有什么索引,使用SHOW INDEX FROM tbl_name。
key
key列显示MySQL实际决定使用的键(索引)。
如果没有选择索引,键是NULL。
要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
key_len
key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。
ref
ref列显示使用哪个列或常数与key一起从表中选择行。
rows
rows列显示MySQL认为它执行查询时必须检查的行数。
Extra
该列包含MySQL解决查询的详细信息。下面解释了该列可以显示的不同的文本字符串:
1, Distinct
MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。
2, Not exists
MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行。
3, range checked for each record(index map: #)
MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
4, Using filesort
MySQL需要额外的一次传递,以找出如何按排序顺序检索行。
5, Using index
从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。当查询只使用作为单一索引一部分的列时,可以使用该策略
。
6, Using temporary
为了解决查询,MySQL需要创建一个临时表来容纳结果。典型情况如查询包含可以按不同情况列出列的GROUP BY和ORDER BY子句时。
7, Using where
WHERE子句用于限制哪一个行匹配下一个表或发送到客户。
8, Using sort_union(...), Using union(...), Using intersect(...)
这些函数说明如何为index_merge联接类型合并索引扫描。
9, Using index for group-by
类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查询GROUP BY或DISTINCT查询的所有列,
而不要额外搜索硬盘访问实际的表。
MySQL优化器会对JOIN、INDEX、GROUP BY、ORDER BY做一些优化
二、MySQL锁
对WRITE,MySQL使用的表锁定方法原理如下
* 如果在表上没有锁,在它上面放一个写锁。
* 否则,把锁定请求放在写锁定队列中。
对READ,MySQL使用的锁定方法原理如下:
* 如果在表上没有写锁定,把一个读锁定放在它上面。
* 否则,把锁请求放在读锁定队列中。
可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:
SHOW STATUS LIKE 'Table%'
三、数据库结构优化
1, 使数据尽可能小
尽可能地使用最有效(最小)的数据类型
尽可能使用较小的整数类型使表更小
如果可能,声明列为NOT NULL
对于MyISAM表,如果没有任何变长列(VARCHAR、TEXT或BLOB列),使用固定尺寸的记录格式
在MySQL/InnoDB中,InnoDB表使用更紧凑的存储格式
紧凑的InnoDB格式也改变了包含UTF-8数据的CHAR列的保存方式
每张表的主索引应该尽可能短
只创建你确实需要的索引
如果很可能一个索引在头几个字符上有唯一的前缀,仅仅索引该前缀比较好
使用列索引和多列索引
索引用于快速找出在某个列中有一特定值的行。
不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。
表越大,花费的时间越多。
如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据。
索引用于下面的操作:
1,快速找出匹配一个WHERE子句的行。
2,删除行。如果可以在多个索引中进行选择,MySQL通常使用找到最少行的索引。
3,当执行联接时,从其它表检索行。
4,对具体有索引的列key_col找出MAX()或MIN()值。由预处理器进行优化,检查是否对索引中在key_col之前发生所有关键字元素使用了WHERE
key_part_# = constant。
四、优化MySQL服务器
这个命令生成所有mysqld选项和可配置变量的列表:
mysqld --verbose --help
如果有一个mysqld服务器正在运行,通过连接它并执行这个命令,可以看到实际上使用的变量的值:
SHOW VARIABLES;
还可以通过下面的语句看到运行服务器的统计和状态指标:
SHOW STATUS;
通常情况若给MySQL更多的内存性能会更好。
当调节MySQL服务器时,要配置的两个最重要的变量是key_buffer_size和table_cache:
mysqld_safe --key_buffer_size=64M --table_cache=256 \
--sort_buffer_size=4M --read_buffer_size=1M &
不同的机器硬件上使用不同的编译器性能也会有不同的提高
已有 1 人发表留言,猛击->>这里<<-参与讨论
JavaEye推荐
- 加入阿里巴巴,发展潜力无限
- 你想过自己的博客制作成书吗 - JavaEye推出博客自动生成电子书功能!
- 搜狐网站诚聘Java、PHP和C++工程师
- Windows7在微软WinHEC 2008上揭开神秘面纱
收录该频道的主题秀
-
搜索不到您的频道?
>立即加入 -
想与您的读者互动?快来认领您的频道
>立即认领 -
想知道您的博客详细订阅数据么?
>到FeedSky查看 -
想体验专业的博客托管服务么?
>注册BlogBus


