MySQL性能优化

MySQL性能优化

大家好,又见面了,我是全栈君。

怎样从MySQL一个数据表中提取一条随机的效率,同一时候要保证效率最高。

方法一

这是最原始最直观的语法。例如以下:

SELECT * FROM foo ORDER BY RAND() LIMIT 1

当数据表中数据量较小时,此方法可行。但当数据量到达一定程度,比方100万数据或以上。就有非常大的性能问题。

假设你通过EXPLAIN来分析这个 语句,会发现尽管MySQL通过建立一张暂时表来排序,但因为ORDER BY和LIMIT本身的特性。在排序未完毕之前,我们还是无法通过LIMIT来获取须要的记录。亦即。你的记录有多少条,就必须首先对这些数据进行排序。

方法二

看来对于大数据量的随机数据抽取,性能的症结出在ORDER BY上,那么怎样避免?方法二提供了一个方案。

首先,获取数据表的全部记录数:

SELECT count(*) AS num_rows FROM foo

然后,通过相应的后台程序记录下此记录总数(假定为num_rows)。

然后运行:

SELECT * FROM foo LIMIT [0到num_rows之间的一个随机数],1

上面这个随机数的获得能够通过后台程序来完毕。此方法的前提是表的ID是连续的或者自增长的。

这种方法已经成功避免了ORDER BY的产生。

方法三

有没有可能不用ORDER BY。用一个SQL语句实现方法二?能够,那就是用JOIN。

SELECT * FROM Bar B JOIN (SELECT CEIL(MAX(ID)*RAND()) AS ID FROM Bar) AS m ON B.ID >= m.ID LIMIT 1;

此方法实现了我们的目的,同一时候,在数据量大的情况下,也避免了ORDER BY所造成的全部记录的排序过程。由于通过JOIN里面的SELECT语句实际上仅仅运行了一次,而不是N次(N等于方法二中的num_rows)。并且, 我们能够在筛选语句上加上“大于”符号。还能够避免由于ID好不连续所产生的记录为空的现象。

在mysql中查询5条不反复的数据,使用下面:

SELECT * FROM `table` ORDER BY RAND() LIMIT 5

就能够了。可是真正測试一下才发现这样效率很低。一个15万余条的库,查询5条数据,竟然要8秒以上

搜索Google,网上基本上都是查询max(id) * rand()来随机获取数据。

SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id ASC LIMIT 5;

可是这样会产生连续的5条记录。解决的方法仅仅能是每次查询一条,查询5次。

即便如此也值得,由于15万条的表,查询仅仅须要0.01秒不到。

上面的语句採用的是JOIN。mysql的论坛上有人使用

SELECT *
FROM `table`
WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` )
ORDER BY id LIMIT 1;

我測试了一下,须要0.5秒,速度也不错。可是跟上面的语句还是有非常大差距。总觉有什么地方不正常。

于是我把语句改写了一下。

SELECT * FROM `table`
WHERE id >= (SELECT floor(RAND() * (SELECT MAX(id) FROM `table`))) 
ORDER BY id LIMIT 1;

这下,效率又提高了,查询时间仅仅有0.01秒

最后。再把语句完好一下。加上MIN(id)的推断。我在最開始測试的时候,就是由于没有加上MIN(id)的推断。结果有一半的时间总是查询到表中的前面几行。
完整查询语句是:

SELECT * FROM `table`
WHERE id >= (SELECT floor( RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`)) + (SELECT MIN(id) FROM `table`))) 
ORDER BY id LIMIT 1;

SELECT *
FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`))+(SELECT MIN(id) FROM `table`)) AS id) AS t2
WHERE t1.id >= t2.id
ORDER BY t1.id LIMIT 1;

最后对这两个语句进行分别查询10次。
前者花费时间 0.147433 秒
后者花费时间 0.015130 秒
看来採用JOIN的语法比直接在WHERE中使用函数效率还要高非常多

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116058.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • TP5 关联模型使用(嵌套关联、动态排序以及隐藏字段)

    TP5 关联模型使用(嵌套关联、动态排序以及隐藏字段)

  • 感觉自己不会的东西太多了,不知道如何下手?

    感觉自己不会的东西太多了,不知道如何下手?GitHub8.8kStar的Java工程师成神之路,不来了解一下吗?GitHub8.8kStar的Java工程师成神之路,真的不来了解一下吗?GitHub8.8kStar的Java工程师成神之路,真的确定不来了解一下吗?如果让我统计下,粉丝问我做多的问题是什么,这个问题肯定可以排前5,问出这个问题的朋友们遍布各个年龄段。实话说,这个问题同样也困扰过我,大概就是我刚…

  • 二叉树的中序遍历非递归算法java_二叉树遍历例题解析

    二叉树的中序遍历非递归算法java_二叉树遍历例题解析*非递归算法思想:  (1)设置一个栈S存放所经过的根结点(指针)信息;初始化S; (2)第一次访问到根结点并不访问,而是入栈;  (3)中序遍历它的左子树,左子树遍历结束后,第二次遇到根结点,就将根结点(指针)退栈,并且访问根结点;然后中序遍历它的右子树。 (4)当需要退栈时,如果栈为空则结束。     代码实现:void…

  • Python正则匹配数字和小数

    Python正则匹配数字和小数正则匹配数字,\为转义字符,d+为匹配一次或多次如下所示:返回的结果为列表  2.正则匹配小数如下所示,返回的结果125.6为字符串 

  • 关于ADRC算法以及参数整定(调参)的一些心得体会

    关于ADRC算法以及参数整定(调参)的一些心得体会关于ADRC算法以及参数整定(调参)的一些心得体会ADRC,全称叫做ActiveDisturbanceRejectionControl,中文名是自抗扰控制技术。这项控制算法是由中科院的韩京清教授提出的。韩教授继承了经典PID控制器的精华,对被控对象的数学模型几乎没有任何要求,又在其基础上引入了基于现代控制理论的状态观测器技术,将抗干扰技术融入到了传统PID控制当中去,最终设计出了适合在工程…

  • Angular面试题_vue框架面试题

    Angular面试题_vue框架面试题一、ng-show/ng-hide与ng-if的区别?第一点区别是,ng-if在后面表达式为true的时候才创建这个dom节点,ng-show是初始时就创建了,用display:block和display:none来控制显示和不显示。第二点区别是,ng-if会(隐式地)产生新作用域,ng-switch、ng-include等会…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号