怎样用mysql查询测试_如何测试数据库查询优化器

我一直认为,查询优化器(Query Optimizer,后面简称优化器)一直是数据库领域 Top 级别的 hardcore 技术,自己也一直尝试去深入理解,但每每看到 TiDB 代码里面那一大坨 plan 的代码,我就望而生畏了,就像是『可远观而不可亵玩焉』。但虽然很难理解,还是能通过方式去理解优化器的,一个最直观的做法就是生成不同的 Query 去验证优化器的效果,实际在 PingCAP 内部,我们也是通过 Fuzz, A/B testing 等技术,来验证优化器是否出现性能问题这些。

但无论怎样,优化器的验证和测试工作是一件非常难的事情,毕竟对于一条 Query,数据库可能会生成非常多的查询计划(plan),我们当然可以通过穷举的方式找到最优的一条 plan,但实际中,我们只能在有限的时间内找到一个比较优的 plan。那么我们如何能确定优化器找到的是一条比较好的 plan 呢?自然需要有一些评价标准,最近看了几篇 Paper,刚好在这个上面做了研究,也对我们后续测试的改良提供了一些方向吧。

OptMark: A Toolkit for Benchmarking Query Optimizers

首先是 OptMark: A Toolkit for Benchmarking Query Optimizers 这篇 Paper,里面提到了验证优化器的两个指标 - Effectiveness 和 Efficiency。对于 Effectiveness 来说,它主要是衡量优化器对于某条 Query 生成的 plan 的质量,而 Efficiency 则是衡量生成的 plan 的资源消耗。

Effectiveness 主要有两个指标,一个是 Performance Factor,一个则是 Optimality Frequency,Performance Factor 计算公式如下:

对于任何 query q 以及优化器 Od 来说,PF 衡量的是在搜索空间里面的 plans,比优化器选择的 plan 要差的比例。Od(q) 是优化器对于 q 生成的 plan,Pd(q) 则是所有可能被执行的 plan,r(D, p) 则是 plan p 执行的时间,而 r(D, Od(q)) 则是优化器选择的 plan 执行的时间。有了 PF,我们就能得到 Optimality Frequency,如果 PF = 1,就表明优化器找到了一条相对不错的 plan。

当然,实际中我们很难将搜索空间全部遍历出来,所以通常我们都只是会找足够多的 plan,Paper 里面提到了 Sample Size 的概念,也就是会有一个信心指数的计算,直白的说,就是如果我们需要有 x% 的信心,以及 y% 的精确度来计算 PF,那么就需要生成 n 个 plans 这种,具体的计算方法可以参考论文 2.1.2 章节。

要验证 Effectiveness,论文使用了如下方式:

对于一条 Query,对里面的 Join 随机进行重新排序

对于 join 的两个 table,如果没有指定 join 方式,则使用 cross join,否则则随机从 joinType() 里面选择一个 physical join,譬如 hash,index merge 等。

对任何 table,随机选择一种扫描方式,譬如使用某个 index,或者全表扫

生成一条 plan,去执行。然后重复执行上述操作,直到满足我们之前说的信心指数。

对于 Efficiency 来说,论文并没有用传统的衡量执行时间的方式,而是选用了 4 个指标:#LP - 枚举的 logical plan个数

#JO - 枚举的 join 顺序个数

#PP - 总的有开销的 physical plan 的个数

#PJ - 总的有开销的 physical join plan 的个数

论文里面将这些指标直接加到了 MySQL 和 PG 的代码里面进行统计,这个也就是开源的好处了,能直接改代码,后面也可以试试 TiDB。

总的来说,OptMark 这篇 Paper 从 Effectiveness 和 Efficiency 两个维度来告诉我们如何测试一个数据库的查询计划,而且也比较容易实施。不过,在测试 Effectiveness 生成 plan 的时候,其实我有点怀疑数据库到底会不会按照这条 plan 去执行。

Counting, Enumerating, and Sampling of Execution Plans in a Cost-Based Query Optimizer

在前面那篇 Paper 里面,OptMark 使用的是一种 random join ordering 的方式来对一条 query 进行 join 的顺序变换,然后对 join 的 table 选择不同的 join 算法,以及对每个 table 使用不同的查询方式,那么有没有其他的办法来对一条 Query 生成执行计划,并且让数据库执行呢?

然后刚好看到了一篇不错的 Paper,Counting, Enumerating, and Sampling of Execution Plans in a Cost-Based Query Optimizer,其中提到了一个很不错的方式,就是通过 MEMO 这种数据结构,来建立好数字和 plan 的对应关系,我们只要给出一个数字,就能执行对应的 plan。

首先,对于一条 Query,我们可以有一个非常简单的 plan,并且用这个 plan 来生成 MEMO 结构

当生成 MEMO 之后,我们就可以对 logical operators 进行变换,一个转换规则可以是:在同一个 group 里面的 logical operator,譬如 join(A, B) -> join(B, A)

在同一个 group 里面的 physical operator,譬如 join -> hash join

一组能连接多个 sub plan 的 logical operators,譬如 join(A, join(B, C)) -> join(join(A, B), C)

然后做完转换之后,MEMO 表现就更丰富了,如下:

最后一项预备工作,就是抽出所有的 physical operators,并且具现化这个 operators 和它们的可能 children 的连接,如下:

当做完了如上三个步骤,就可以通过 MEMO 这个数据结构算出来总的 Query Plans,算法可以直接看 Paper 3.2 章节,其实就是自下而上遍历每个可能 plan 的个数并且汇总。当我们得到了总的 plan 个数,就可以通过 unranking 算法知道某个 position 上面对应的 plan,具体的 unranking 算法可以参考 3.2。当构造了这些信息之后,我们就可以在 query 里面直接指定使用某个 plan 了,如下:

其实这个方式非常的巧妙,现在 TiDB 是不支持的,没准可以试试支持下,应该也不困难。

Testing the Accuracy of Query Optimizers

除了上面两篇 Paper,还看了一篇,Testing the Accuracy of Query Optimizers,讲的是如何测试优化器的精确度,其实就是一个 estimate time 和实际 execution time 的 pair 对比吧,会计算一个相关性 score,类似如下:

可以看到,上面 4 个 plan,P1 和 P2 其实明显会比 P3 和 P4 要好。

然后 Paper 的作者做了一个 TAQO 系统,如下:

流程比较通俗易懂,不多做解释了,反正可以结合上面第一篇 paper,来验证优化器的效果吧。

总结

上面列了几篇,我们当然是想应用到 TiDB 来验证优化器的效果的,当然另外,我们也可以通过让优化器强制使用不用的 plan,来看优化器会不会有 bug,譬如对于第二篇 paper,没准我们使用 plan 8 得到的值跟 plan 9 不一样,这事情就有意思了。

总的来说,优化器这个方向是一个非常 hardcore 的东西,不光是测试上面,还包括如何实现一个高效的优化器上面,我们需要非常多的技术储备,如果你对这方面感兴趣,欢迎联系我 tl@pingcap.com。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531744.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

poj2060Taxi Cab Scheme(二分图匹配)

1 /*2 题意: 出租车 有一个出发的时间,从点(a, b)到点(c, d),时间为3 abs(a-c)abs(b-d)! 一辆车可以在运完一个乘客后运另一个乘客, 4 条件是此车要在预约开始前一分钟之前到达出发地,…

二级java考什么_计算机二级Java考试资料!

Where领?基本要求1 . 掌握 Java 语言的特点、实现机制和体系结构。2 . 掌握 Java 语言中面向对象的特性。3 . 掌握 Java 语言提供的数据类型和结构。4 . 掌握 Java 语言编程的基本技术。5 . 会编写 Java 用户界面…

二分匹配最大匹配的理解(附图解)

定义一个PXP的有向图中,路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联;(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每…

poj 2226 Muddy Fields(合理建图+二分匹配)

1 /*2 题意:用木板盖住泥泞的地方,不能盖住草。木板任意长!可以重叠覆盖! *表示泥泞的地方,.表示草!3 思路:4 首先让我们回忆一下HDU 2119 Matrix这一道题,一个矩阵…

java验证码工具_java 验证码工具

importjavax.imageio.ImageIO;import java.awt.*;importjava.awt.image.BufferedImage;importjava.io.IOException;importjava.io.OutputStream;importjava.util.Random;public classCaptchaUtils {private final static Object lock newObject();/*** 图片的宽度。*/private …

Floyd算法的理解

转载于:https://www.cnblogs.com/hujunzheng/p/3919226.html

http get post java_java发送http的get、post请求实现代码

Http请求类package wzh.Http;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.URL;import java.net.URLConnection;import java.util.List;import java.util.Map;public class HttpRe…

java string的作用_浅谈java String不可变的好处

一、java内部String类的实现:java 8:public final class Stringimplements java.io.Serializable, Comparable, CharSequence {/** The value is used for character storage. */private final char value[];}java 9 及之后:(使用coder标识了…

34988 Happy Reversal(二进制去取反)

1 /*2 题意:给多个二进制数,对某些数进行按位取反操作!3 然后从中找到最大数和最小数,并输出他们的差值! 4 注意:所有的数都是整数,包括取反之后5 6 思路:一个n为二进…

java vim ide_Vim配置Java IDE

首先安装vim (当然做java 开发要装jdk 这个就不说了)emerge -av vim (gentoo 系统上安装vim 的命令,你可以用rpm ,apt-get )给vim 安装 javacomplete 插件http://www.vim.org/scripts/script.php?script_id1785 这个插件的作用是实现一部分代码提示功能 比如你输入 System…

java中线程存活和线程执行的问题!

1 /*2 下面的程序会出现下面的情况,当Thread-0, Thread-1, Thread-2都被wait的时候,可能会同时苏醒3 Thread-0 put4 Thread-1 put5 Thread-2 put6 Thread-3 get//在此处,Thread-3拿到锁之后&#xff0…

java中多线程模拟(多生产,多消费,Lock实现同步锁,替代synchronized同步代码块)...

import java.util.concurrent.locks.*; class DuckMsg{int size;//烤鸭的大小String id;//烤鸭的厂家和标号DuckMsg(){}DuckMsg(int size, String id){this.sizesize;this.idid;}public String toString(){return id " 大小为:" size;} } class Duck{private int …

java encode 空格_javaWeb中URLEncoder.encode空格问题

近期开发一个在线坐席的功能。发现推送的消息中空格变成了 。查询发现URLEncoder.encode的问题。曾经用的时候也没注意过,解决的方法网上是对URLEncoder.encode的之后的字符串进行替换号,这样的方式假设真的有号那也被替换了。所以应该在URLEncoder.enco…

poj 1386 Play on Words(有向图欧拉回路)

1 /*2 题意:单词拼接,前一个单词的末尾字母和后一个单词的开头字母相同3 思路:将一个单词的开头和末尾单词分别做两个点并建一条有向边!然后判断是否存在欧拉回路或者欧拉路 4 5 再次强调有向图欧拉路或欧拉回路的判定方法&…

java web tomcat 实例_Java Web应用开发实例

[1.GIS的概念 1.1什么是gis 地理信息系统 (GIS, Geographic Information System) 是一种基于计算机的工具,它可以对在地球上存在的东西和发生的事件进行成图和分析。 GI上次提到了EclipseTomcatLomboz Java Web开发环境的配置,可环…

poj2513Colored Sticks(无向图的欧拉回路)

1 /*2 题意:将两端涂有颜色的木棒连在一起,并且连接处的颜色相同!3 思路:将每一个单词看成一个节点,建立节点之间的无向图!判断是否是欧拉回路或者是欧拉路4 5 并查集判通 奇度节点个数等于2或…

java java.lang.enum_源码阅读-java基础-java.lang.Enum

1、引言枚举类型是 JDK 5 之后引进的一种非常重要的引用类型,可以用来定义一系列枚举常量。相比与常量(public static final定义),在安全性、指意性、可读性方面更胜一筹。另外它可以和switch case搭配使用。2、类定义实际上在使用关键字enum创建枚举类型…

java中有关线程的题目

1,看一下下面程序错误发生在哪一行! class Test implements Runnable{public void run(Thread t){} }2,输出结果是什么? class Test{public static void main(String[] args){new Thread(new Runnable(){public void run(){System…

java 可逆的加密算法_java实现AES可逆加密算法

package com.hdu.encode;import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;/*** AES 是一种可逆加密算法,对用户的敏感信息加密处理 对…

森林转换成二叉树以及二叉树还原为森林代码

1 /*2 森林转换成二叉树3 思路:u的孩子节点为v1, v2, v3....(v1,v2,....互为兄弟节点) 4 那么将u的一个孩子节点(v1)连在u的左子树上,那么其他的孩子节点都连在v1的右子树上! 5 …