我建立一个网站,我需要从数据库中选择随机加权记录 。大数据库快速mysql随机加权选择
还有就是代码SQL : select one row randomly, but taking into account a weight
SELECT t.*, RAND() * t.weight AS w FROM table t ORDER BY w DESC LIMIT 1
它适用于记录小样本罚款文档片断。
尝试接近100万条记录时,它在本地机器上变慢(1.3 - 1.8秒) ,我想我会在更大的机器上花费更长的时间。
它如何优化? 有没有更好的方法随机选择加权记录?
我的尝试是定期计算权重,将它们存储在单独的表中,选择随机数programmaticaly并搜索最接近该记录的记录。
您可以根据权重对数据进行分区,然后随机选择一个分区。
确定要使用的分区:O(n)的
SELECT Weight, FLOOR(RAND()*COUNT(*)) as Target FROM test GROUP BY Weight ORDER BY RAND()*(Weight)*count(Weight)/100 DESC LIMIT 1;
使用权,并从以前的查询目标得到的结果:O(日志(n))的
SELECT test.* FROM test WHERE Weight = $Weight LIMIT $Target, 1
测试:
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)运行时间。
我与第一个查询中(6.089 s)运行测试表800万行和(0.001 s)
|