我有超过6000个结果,使用分页来获得超过235页。当我点击第一页时,它加载的速度非常快〜300毫秒,直到第40页左右。之后它真的下山了大约30~40+秒的页面加载时间。我正在使用索引数据库。我试过用mysql catch查询,但是不喜欢它。有人可以帮助我。
PHP:
$sql = mysql_query("SELECT * FROM data WHERE (car = '$cars') AND (color = '$color' AND price BETWEEN '".$min."' AND '".$max."'
ORDER BY price LIMIT {$startpoint} , {$limit}");
指数:
data 0 PRIMARY 1 id A 106199 NULL NULL BTREE
data 1 car_index 1 car A 1799 NULL NULL BTREE
data 1 car_index 2 color A 2870 NULL NULL BTREE
data 1 car_index 3 price A 6247 NULL NULL BTREE
data 1 car_index 4 location A 106199 NULL NULL BTREE
答案 0 :(得分:0)
在这里发布表结构以查看您拥有的索引是个好主意。 请在列价上添加一个索引,它应该可以提高查询性能。
干杯
答案 1 :(得分:0)
这是MySQL(和其他数据库系统)的常见问题。使用LIMIT + OFFSET(你正在使用LIMIT x,y隐含地使用它)一开始工作得很好,但随着读取行数的增加,指数速度会减慢。 添加索引绝对是一个很好的第一步,因为您应该始终根据索引查询数据,以避免全表扫描。
由于您拥有其他WHERE属性,因此只有价格索引是不够的。基本上,这就是MySQL正在做的事情:
假设$limit = 25
和$startPoint = 0
,MySQL将从头开始读取表,并在找到25个匹配行后停止并返回它们。让我们假设它为第一次迭代读取了500行。下一次迭代,因为它没有car + color + price
上的索引,它不知道如何直接跳转到第25个匹配行(表中的第500行),所以它将从头开始再次读取,跳过前25个匹配的行并返回25个下一个匹配的行。我们假设这个迭代还需要读取500个额外的行。
现在你看到出了什么问题。对于每次迭代,MySQL都必须从头开始读取所有行,以指数方式增加返回行所需的时间。
在我的示例中,要获取100(25 * 4次迭代)行,MySQL必须读取500 + 1000 + 1500 + 2000 = 5000行,而您可以预期它只读取500 * 4 = 2,000行。要获取1000(25 * 40次迭代)行,MySQL必须读取500 + 1000 + 1500 + ... 20000 = 410,000行!这比你预期的500 * 40 = 20,000行还多。
要优化查询,请先选择所需的数据(否SELECT *
)。然后诀窍是记住最后获取的id。
$lastFetchedId = 0;
do {
$sql = mysql_query("SELECT * FROM data WHERE id > $lastFetchedId AND (car = '$cars' AND color = '$color' AND price BETWEEN '".$min."' AND '".$max."')
ORDER BY price LIMIT {$limit}");
$hasFoundRows = false;
while ($row = mysql_fetch_assoc($sql)) {
$hasFoundRows = true;
$lastFetchedId = $row['id'];
// do something with the row
}
} while ($hasFoundRows === false);
只有在WHERE子句中使用的所有列都有索引时,让MySQL处理顺序才能正常工作。这样考虑:如果数据没有排序,MySQL将如何知道哪些行匹配以及匹配的行在哪里。为了能够对结果进行排序并仅返回子集,MySQL需要构建实际匹配的所有行的排序列表。这意味着遍历整个表首先获取所有匹配的行,然后对它们进行排序,最后只返回其中的几个。
希望能帮助您更好地了解您可以在这里做得更好:)