首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >php分页在大页面或最后一页上速度较慢

php分页在大页面或最后一页上速度较慢
EN

Stack Overflow用户
提问于 2015-08-23 08:44:46
回答 2查看 1.1K关注 0票数 0

我有超过6000个结果,使用分页大约超过235页。当我点击第一页时,它加载的速度非常快,大约300ms,直到第40页。在那之后,页面加载时间就会下降,大约需要30 ~ 40+秒。我使用的是索引数据库。我试着用mysql捕获查询,但不喜欢它。谁能帮帮我。

php:

代码语言:javascript
复制
$sql = mysql_query("SELECT * FROM data WHERE (car = '$cars') AND (color = '$color' AND price BETWEEN '".$min."' AND '".$max."'  
ORDER BY price LIMIT {$startpoint} , {$limit}");

索引:

代码语言:javascript
复制
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       
EN

回答 2

Stack Overflow用户

发布于 2015-08-23 09:54:49

这是MySQL (和其他数据库系统)的常见问题。使用LIMIT + OFFSET (这是您隐含地与LIMIT x,y一起使用的)一开始效果很好,但随着读取的行数增加,速度会呈指数级下降。添加索引绝对是很好的第一步,因为您应该始终基于索引查询数据,以避免全表扫描。

仅仅有一个关于价格的索引是不够的,因为你还有其他的WHERE属性。基本上,这就是MySQL正在做的事情:假设$limit = 25$startPoint = 0,MySQL将从头开始读取表,并在找到25个匹配的行后停止并返回它们。假设它在第一次迭代中读取了500行。因为它不知道如何直接跳转到第25个匹配行(表中的第500行),所以它将再次从头开始读取,跳过前25个匹配行并返回下一个匹配行。让我们假设这个迭代还需要读取500个额外的行。

现在您知道问题出在哪里了。对于每次迭代,MySQL将不得不从头开始读取所有行,这将以指数级增加返回row所需的时间。

在我的示例中,要获取100 (25 *4次迭代)行,MySQL必须读取500 + 1000 + 1500 + 2000 = 5000行,而您可以预期它只读取500 *4=2000行。要获取1000 (25 * 40次迭代)行,MySQL必须读取500 + 1000 + 1500 + ... 20000 = 410,000行!!这远远超过了您预期的500 * 40 = 20,000行。

为了优化您的查询,首先只选择您需要的数据(没有SELECT *)。那么诀窍就是记住最后获取的id。

代码语言:javascript
复制
$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需要构建一个包含所有实际匹配的行的排序列表。这意味着遍历整个表,首先获取所有匹配的行,然后对它们进行排序,最后只返回其中的一小部分。

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

票数 1
EN

Stack Overflow用户

发布于 2015-08-23 08:55:54

最好在这里发布表结构,看看您有哪些索引。请在列价格上添加索引,这样可以提高查询性能。

干杯

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32162136

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档