Php 按rand()查询订单速度太慢

Php 按rand()查询订单速度太慢,php,mysql,Php,Mysql,我在数据库中有一个名为offersover 300.000 rows的大表 当我执行下面的查询时,它需要超过3秒 $sql = "SELECT * FROM `offers` WHERE (`start_price` / `price` >= 2) ORDER BY RAND() LIMIT 1"; 餐桌优惠 `id` int(11) NOT NULL, `title` text NOT NULL, `description` text NOT NULL, `image` text N

我在数据库中有一个名为offersover 300.000 rows的大表

当我执行下面的查询时,它需要超过3秒

$sql = "SELECT * FROM `offers` WHERE (`start_price` / `price` >= 2) ORDER BY RAND() LIMIT 1"; 
餐桌优惠

`id` int(11) NOT NULL,
`title` text NOT NULL,
`description` text NOT NULL,
`image` text NOT NULL,
`price` float NOT NULL,
`start_price` float NOT NULL,
`brand` text NOT NULL

有没有办法让它更快?我想随机选择一行start\u price/price>=2

有备选方案。我所使用的一种方法如下所述:-

基本上,您会生成一个介于最小id和最大id之间的随机数,然后使用>=将其与结果集合并,限制为1。因此,您可以从完整结果中的随机点开始获得结果集,然后仅获取第一条记录

不利的一面是,若id字段分布不均匀,那个么它就不是真正随机的

快速示例代码,假设您的offers表有一个名为id的唯一键:-

SELECT offers.* 
FROM offers 
INNER JOIN 
(
    SELECT RAND( ) * ( MAX( Id ) - MIN( Id ) ) + MIN( Id ) AS Id
    FROM offers
    WHERE (`start_price` / `price` >= 2)
) AS r2
ON offers.Id >= r2.Id
WHERE (`start_price` / `price` >= 2) 
ORDER BY offers.Id LIMIT 1

加快此速度的一个选项是确保利用索引:

因此,在这种情况下,请确保您有一个起始价格指数,以及价格指数,并按照正确的顺序排列

另一种方法是优化用于数据库和表的联盟,因此选择utf8mb4而不是utf8,如果排序/本地化不是您的问题,并且您希望完全分析,则选择常规ci而不是unicode ci:

尽管MyISAM存储引擎提供了更快的读取速度,但我发现InnoDB存储引擎有各种各样的调整,可以比我使用MyISAM实现的速度更快:

因此,类似于以下内容的内容将是另一种选择:

[mysqld] // Don't play here unless you have read and understand what is going on
innodb_read_io_threads=64
innodb_write_io_threads=64
innodb_buffer_pool_size=2G
另一个选择是查看备用存储引擎:


您还可以看到重构查询的其他答案:

我认为您的问题是查询需要对WHERE子句进行完整的表扫描。order by确实会让事情变得更糟——这取决于通过过滤器的音量

您可以考虑将这个数字存储在表中,并添加一个索引:

alter table offers add column start_to_price float;

update offers
    set start_to_price = start_price / price;

create index idx_offers_s2p on offers(start_to_price);
然后,您的查询可能会很快:

SELECT o.*
FROM `offers` o 
WHERE start_to_price >= 2
ORDER BY RAND()
LIMIT 1;
如果性能仍然是一个问题,那么我可能会首先使用where子句:

SELECT o.*
FROM `offers` o CROSS JOIN
     (select COUNT(*) as cnt from offers where start_to_price >= 2) oo
WHERE rand() <= 10 / cnt
ORDER BY RAND()
LIMIT 1;
这将随机抽取大约10行,然后选择其中一行


如果这些都不起作用,那么还有其他解决方案会变得越来越复杂。

不要对查询排序,而是使用php从结果中随机选取一行?生成随机id,然后传递到查询。花费更少的时间。请注意,将价格存储为浮动有点奇怪。我认为说:价格*2<开始更快_price@Strawberry为什么您认为使用price*2