大页面或最后一页上的php分页速度慢

时间:2015-08-23 00:44:46

标签: php performance pagination

我有超过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       

2 个答案:

答案 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需要构建实际匹配的所有行的排序列表。这意味着遍历整个表首先获取所有匹配的行,然后对它们进行排序,最后只返回其中的几个。

希望能帮助您更好地了解您可以在这里做得更好:)