Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
大型数据库上的快速mysql随机加权选择_Mysql_Sql_Random - Fatal编程技术网

大型数据库上的快速mysql随机加权选择

大型数据库上的快速mysql随机加权选择,mysql,sql,random,Mysql,Sql,Random,我建立了一个网站,我需要选择随机加权记录 从数据库 里面有一段代码 它在小样本记录上运行良好 当尝试接近1百万条记录时,速度会变慢(1.3-1.8秒) 在我本地的机器上,我想在更大的电视机上我会花更长的时间 如何对其进行优化? 是否有更好的方法随机选择加权记录 我的尝试是定期计算权重,将它们存储在单独的表中,选择random number programmaticaly并搜索与该数字最接近的记录。您可以根据权重对数据进行分区,然后随机选择一个分区 确定要使用的分区:O(n) 使用上一次查询中的权

我建立了一个网站,我需要选择随机加权记录 从数据库

里面有一段代码

它在小样本记录上运行良好

当尝试接近1百万条记录时,速度会变慢(1.3-1.8秒) 在我本地的机器上,我想在更大的电视机上我会花更长的时间

如何对其进行优化? 是否有更好的方法随机选择加权记录


我的尝试是定期计算权重,将它们存储在单独的表中,选择random number programmaticaly并搜索与该数字最接近的记录。

您可以根据权重对数据进行分区,然后随机选择一个分区

确定要使用的分区:O(n)

使用上一次查询中的权重和目标来获得结果:O(Log(n))

测试它:

CREATE TABLE `test` (
  `Id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `Weight` int(11) NOT NULL,
  PRIMARY KEY (`Id`),
  KEY `Weight` (`Weight`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


insert into test (Weight) ( select FLOOR(RAND()*1000) );
运行20次以创建100万个测试行:

insert into test (Weight) select FLOOR(rand()*1000) as Weight from test;
由于GROUP BY,第一个查询在O(n)中运行。如果您维护第二个表来跟踪每个重量的计数,则可以将其记录到log(n)运行时间


在我的数据库中,测试表中有800万行,第一个查询在
(6.089 s)
中运行,第二个查询在
(0.001 s)

中首先获取所有权重的总和,以便您可以计算动态选择每一行的概率

SELECT SUM(weight) FROM t;
我假设总和可以通过名为@TOTAL_WEIGHT的mysql变量访问

SELECT t.* 
FROM t
WHERE RAND() <= (weight / @TOTAL_WEIGHT)
ORDER BY RAND()
LIMIT 1;
选择t.*
从t

这在哪里回答了你的问题?
insert into test (Weight) select FLOOR(rand()*1000) as Weight from test;
SELECT SUM(weight) FROM t;
SELECT t.* 
FROM t
WHERE RAND() <= (weight / @TOTAL_WEIGHT)
ORDER BY RAND()
LIMIT 1;