简而言之:一个包含超过1600万条记录的表[大小为2GB].使用ORDER BY*primary_key时,使用SELECT的LIMIT偏移越高,查询变得越慢
所以
SELECT * FROM large ORDER BY `id` LIMIT 0, 30
Run Code Online (Sandbox Code Playgroud)
远远不及
SELECT * FROM large ORDER BY `id` LIMIT 10000, 30
Run Code Online (Sandbox Code Playgroud)
这也只能订购30条记录.所以这不是ORDER BY的开销.
现在,当获取最新的30行时,大约需要180秒.如何优化该简单查询?
我有一张很大的桌子.它目前在MySQL数据库中.我用django.
我需要迭代表中的每个元素来预先计算一些特定的数据(也许如果我更好,我可以做其他事情,但这不是重点).
我希望通过不断使用内存来尽可能快地保持迭代.
因为它已经明确地限制了*Large*Django QuerySet中的内存使用以及为什么要遍历大量Django QuerySet消耗大量内存?,对django中所有对象的简单迭代将终止机器,因为它将从数据库中检索所有对象.
首先,为了减少你的内存消耗,你应该确保DEBUG是假的(或者修补游标:关闭SQL日志记录,同时保持settings.DEBUG?)以确保django不存储connections调试内容.
但即便如此,
for model in Model.objects.all()
Run Code Online (Sandbox Code Playgroud)
是不行的.
甚至没有稍微改进的形式:
for model in Model.objects.all().iterator()
Run Code Online (Sandbox Code Playgroud)
使用iterator()将通过不在内部存储缓存的结果来节省一些内存(虽然不一定在PostgreSQL上!); 但显然仍会从数据库中检索整个对象.
第一个问题的解决方案是基于计数器对结果进行切片chunk_size.有几种方法可以编写它,但基本上它们都归结为OFFSET + LIMITSQL中的查询.
就像是:
qs = Model.objects.all()
counter = 0
count = qs.count()
while counter < count:
for model in qs[counter:counter+count].iterator()
yield model
counter += chunk_size
Run Code Online (Sandbox Code Playgroud)
虽然这是内存效率(恒定的内存使用量成比例chunk_size),但它在速度方面确实很差:随着OFFSET的增长,MySQL和PostgreSQL(以及可能是大多数数据库)都会开始窒息和放慢速度.
Thierry Schellenbach 在这篇文章中提供了一个更好的解决方案.它过滤PK,这比抵消更快(可能有多快取决于DB)
pk = 0 …Run Code Online (Sandbox Code Playgroud) 正如你们中的一些人所知,在MySQL中使用LIMIT关键字并不妨碍它阅读前面的记录.
例如:
SELECT * FROM my_table LIMIT 10000, 20;
Run Code Online (Sandbox Code Playgroud)
意味着MySQL仍将读取前10,000条记录,并在生成我们追踪的20条记录之前抛弃它们.
因此,在对大型数据集进行分页时,高页码意味着加载时间过长.
有没有人知道任何现有的分页类/技术/方法可以以更有效的方式对大型数据集进行分页,即不依赖于LIMIT MySQL关键字?
在PHP中,如果可能的话,因为这是我公司的首选武器.
干杯.
我正在使用MySQL 中的SQL 限制db.Records来实现分页,需要得到
从最后一行向后检索。表中有几千条记录
我想一次检索 500 条记录以显示在页面中。
SELECT * FROM tbl_name ORDER BY some_col DESC
Run Code Online (Sandbox Code Playgroud)
将检索所有记录。
但我不想要所有记录,因为它们的数量有数千个。
如果我使用
SELECT * FROM tbl_name ORDER BY some_col DESC LIMIT 500
Run Code Online (Sandbox Code Playgroud)
它将按降序返回最后 500 条记录。
但我找不到从第一个块剩下的点开始反向检索下一个 500 块的方法。
我有一个目录,我使用下面的PHP脚本构建,它使用分页每页获得1002个结果.问题是你进入页面的距离越远,他们加载的时间就越长.例如,第1页的加载速度明显快于第10,000页.
我猜测我对查询做了一些错误,而不仅仅是选择1002结果它应该被限制,它也会循环遍历它之前的所有结果.如果有人可以发布需要修复的代码,那就太棒了!
感谢您的时间和帮助!
<?php include("websites/header.html"); ?>
<center>
<?php
/*
Place code to connect to your DB here.
*/
include('websites/database.php'); // include your code to connect to DB.
$tbl_name="list"; //your table name
// How many adjacent pages should be shown on each side?
$adjacents = 5;
/*
First get total number of rows in data table.
If you have a WHERE clause in your query, make sure you mirror it here.
*/
$query = "SELECT COUNT(*) as num FROM $tbl_name";
$total_pages …Run Code Online (Sandbox Code Playgroud) mysql ×4
sql ×3
pagination ×2
php ×2
database ×1
django ×1
html ×1
limit ×1
logic ×1
performance ×1
sql-order-by ×1