zoukankan      html  css  js  c++  java
  • MySQL随机获取数据的方法,支持大数据量

    最近做项目,需要做一个从mysql数据库中随机取几条数据出来。
    总所周知,order by rand 会死人的。。因为本人对大数据量方面的只是了解的很少,无解,去找百度老师。。搜索结果千篇一律。特发到这里来,供大家学习。

    在mysql中带了随机取数据的函数,在mysql中我们会有rand()函数,很多朋友都会直接使用,如果几百条数据肯定没事,如果几万或百万时你会发现,直接使用是错误的。下面我来介绍随机取数据一些优化方法。

    1. SELECT * FROM table_name ORDER BY rand() LIMIT 5;
    复制代码

    rand在手册里是这么说的:
    RAND()
    RAND(N)
    返回在范围0到1.0内的随机浮点值。如果一个整数参数N被指定,它被用作种子值。

    1. mysql> select RAND();
    2.         -> 0.5925
    3. mysql> select RAND(20);
    4.         -> 0.1811
    5. mysql> select RAND(20);
    6.         -> 0.1811
    7. mysql> select RAND();
    8.         -> 0.2079
    9. mysql> select RAND();
    10.         -> 0.7888
    复制代码

    你 不能在一个ORDER BY子句用RAND()值使用列,因为ORDER BY将重复计算列多次。然而在MySQL3.23中,你可以做: SELECT * FROM table_name ORDER BY RAND(),这是有利于得到一个来自SELECT * FROM table1,table2 WHERE a=b AND c<d ORDER BY RAND() LIMIT 1000的集合的随机样本。注意在一个WHERE子句里的一个RAND()将在每次WHERE被执行时重新评估。

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

    1. SELECT *
    2. FROM `table` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `table`)) AS id) AS t2
    3. WHERE t1.id >= t2.id
    4. ORDER BY t1.id ASC LIMIT 5;
    复制代码

    但是这样会产生连续的5条记录。解决办法只能是每次查询一条,查询5次。即便如此也值得,因为15万条的表,查询只需要0.01秒不到。

    上面的语句采用的是JOIN,mysql的论坛上有人使用

    1. SELECT *
    2. FROM `table`
    3. WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` )
    4. ORDER BY id LIMIT 1;
    复制代码

    我测试了一下,需要0.5秒,速度也不错,但是跟上面的语句还是有很大差距
    后来请教了baidu,得到如下代码
    完整查询语句是:

    1. SELECT * FROM `table`
    2. WHERE id >= (SELECT floor( RAND() * ((SELECT MAX(id) FROM `table`)-(SELECT MIN(id) FROM `table`)) + (SELECT MIN(id) FROM `table`))) 
    3. ORDER BY id LIMIT 1;
    复制代码
    1. SELECT *
    2. 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
    3. WHERE t1.id >= t2.id
    4. ORDER BY t1.id LIMIT 1;
    复制代码

    最后在php中对这两个语句进行分别查询10次,
    前者花费时间 0.147433 秒
    后者花费时间 0.015130 秒

    执行效率需要0.02 sec.可惜的是,只有mysql 4.1.*以上才支持这样的子查询.
    注意事项 查看官方手册,也说rand()放在ORDER BY 子句中会被执行多次,自然效率及很低。

    以上的sql语句最后一条,本人实际测试通过,100W数据,瞬间出结果。

  • 相关阅读:
    BadUSB 利用
    java 将函数作为参数传递
    odoo12 修行提升篇之 常用的高阶函数 (二)
    odoo12 修行提升篇之 异步定时任务 (一)
    odoo12 修行基础篇之 利用kanban做分析 点击跳转分析模型列表 (九)
    odoo12 修行基础篇之 kanban (八)
    odoo12 修行基础篇之 记录批处理 (七)
    odoo12 修行基础篇之 列表的筛选和分组 (六)
    odoo12 修行基础篇之 添加记录编码 (五)
    odoo12 修行基础篇之 添加工作流和操作记录 (四)
  • 原文地址:https://www.cnblogs.com/langtianya/p/5352893.html
Copyright © 2011-2022 走看看