我需要从具有特定类别ID和价格范围的大型MySQL表(~9000000行,4.5GiB)中选择一个随机产品。
我现在使用的解决方案大约需要30秒才能完成请求。
$query = mysqli_query($db, "SELECT MAX(id) FROM `products` WHERE category = $cat AND price >= $price_min AND price <= $price_max");
$f = mysqli_fetch_array($query);
$max_id = $f[0];
$random_id = rand(0, $max_id);
mysqli_free_result($query);
$query = mysqli_query($db, "SELECT * FROM `products` id=$random_id LIMIT 1");
$product = mysqli_fetch_assoc($query);
是否可以优化请求?
答案 0 :(得分:1)
要获得一定的速度,您需要考虑确保category
有索引。
但如果你使用它,你可以删除一个查询:
$query = mysqli_query(
$db,
"
SELECT *
FROM `products`
WHERE
`category` = $cat
AND `price` BETWEEN $price_min AND $price_max
ORDER BY RAND()
LIMIT 1
"
);
$product = mysqli_fetch_assoc($query);
希望这有帮助。
答案 1 :(得分:1)
使用EXPLAIN
查看查询的执行计划。确保MySQL正在使用适当的索引来满足查询。
参考:https://dev.mysql.com/doc/refman/5.5/en/using-explain.html
此查询的相应索引将category
作为前导列,后跟price
,并包含id
列。
举个例子:
CREATE INDEX products_IX1 ON products (category, price, id);
有了这个索引,我们期望EXPLAIN
输出显示MySQL正在使用前两列对索引执行范围扫描操作(由key_len
指示我们还希望EXPLAIN输出显示&#34;使用索引&#34;在Extra列中,因为索引是&#34;覆盖&#34;查询的索引。
注意强>
这与您提出的问题无关,但是......
代码示例易受攻击到 SQL注入。结合到SQL语句文本中的潜在不安全值必须正确转义。
http://php.net/manual/en/mysqli.real-escape-string.php
更好的模式是使用预备语句和绑定占位符。