我需要在列表视图中显示SQLite结果.当然,我需要分页结果.
第一种选择是使用LIMIT子句.例如:
SELECT * FROM Table LIMIT 100, 5000
Run Code Online (Sandbox Code Playgroud)
它返回记录5001到5100.问题是内部SQLite"读取"前5000条记录并且效率不高.
当有大量记录时,分页的最佳方法是什么?
我的应用拥有属于用户的照片.
在照片#show视图中,我想显示"来自此用户的更多内容",并显示该用户的下一张和上一张照片.我会很好,这些是id
顺序的下一张/上一张照片或下一张/上一张照片created_at
.
您如何为下一张/上一张照片或多张下一张/上一张照片撰写此类查询?
我有一张很大的桌子.它目前在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 + LIMIT
SQL中的查询.
就像是:
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) 在使用大偏移LIMIT
的mysql 时遇到性能问题SELECT
:
SELECT * FROM table LIMIT m, n;
Run Code Online (Sandbox Code Playgroud)
如果偏移m
量大于1,000,000,则操作非常慢.
我必须使用limit m, n
; 我不能用类似的东西id > 1,000,000 limit n
.
如何优化此声明以获得更好的性能?
例如,您有一个按优先级排序的项目列表.你有10,000件物品!如果您向用户显示单个项目,如何为用户提供按钮以查看上一个项目或下一个项目(这些项目是什么)?
您可以将项目的位置传递给项目页面,并在SQL查询中使用OFFSET.除了必须传递可能改变的数字之外,其缺点是数据库无法跳转到偏移量; 它必须读取每条记录,直到它达到第9001条记录.这很慢.搜索了一个解决方案,我找不到一个,所以我写了order_query.
order_query使用相同的ORDER BY查询,但还包括一个WHERE子句,该子句排除当前(下一个)之前或之后(对于prev)的记录.
以下是标准的示例(使用上面的gem):
p = Issue.find(31).relative_order_by_query(Issue.visible,
[[:priority, %w(high medium low)],
[:valid_votes_count, :desc, sql: '(votes - suspicious_votes)'],
[:updated_at, :desc],
[:id, :desc]])
p.before #=> ActiveRecord::Relation<...>
p.previous #=> Issue<...>
p.position #=> 5
p.next #=> Issue<...>
p.after #=> ActiveRecord::Relation<...>
Run Code Online (Sandbox Code Playgroud)
我刚刚在这里重新发明了轮子吗?我对在后端执行此操作的其他方法非常感兴趣.
在内部,这个gem构建一个依赖于当前记录的订单值的查询,如下所示:
SELECT ... WHERE
x0 OR
y0 AND (x1 OR
y1 AND (x2 OR
y2 AND ...))
ORDER BY ...
LIMIT 1
Run Code Online (Sandbox Code Playgroud)
凡x
符合>
/ <
条款,并y
以=
条款(解决关系),每个订单的标准.
来自测试套件日志的示例查询:
-- Current record: priority='high' …
Run Code Online (Sandbox Code Playgroud) 我想获得我的表的最后20个条目,但按升序ID排序.
在Sql中它不是很复杂:
SELECT *
FROM (SELECT * FROM comments
WHERE postID='$id'
ORDER BY id DESC
LIMIT 20) t
ORDER BY id ASC;
Run Code Online (Sandbox Code Playgroud)
但我想用我的yii模型:
Comment::model()->findAll($criteria)
Run Code Online (Sandbox Code Playgroud)
但我真的不知道我应该把什么放在我的CDbCriteria中!
我有一张带有int
田地的桌子,让我们称之为createTime
.该表包含数百万条记录.现在我想运行查询:
select * from `table` order by `createTime` desc limit 500000, 10
Run Code Online (Sandbox Code Playgroud)
我已经创建了一个索引createTime
,但查询运行缓慢.什么原因?我怎样才能改进它?
这是EXPLAIN所说的:
id 1
select_type simple
table table
type index
possible_keys null
key createTime
key_len 4
ref null
rows 500010
extra
Run Code Online (Sandbox Code Playgroud)
至于偏移量,当它很小时它的工作速度要快得多.
我们正在构建一个我们刚刚构建的CMS中的CSV导出机制,但是我们无法在具有数百万行的结果集上保留内存.将MySQL(通过mysql2
gem)的1MM +行结果写入CSV 的最佳方法是什么?如果它有任何区别,我们使用的是Ruby 1.9.3p194和MySQL 5.5.我们的主要目标是在Ruby进程上保持内存消耗.
我有一个目录,我使用下面的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) I have 8 millions of records in table and this query is just too slow. It's for sitemap (that we need to index it all). In this example I choose 1000 items from position 6 millions.
SELECT source, identifier
FROM mh_download
WHERE deleted =0
LIMIT 6000000 , 1000
Run Code Online (Sandbox Code Playgroud)
33 seconds
Table is MyISAM and column deleted has index. MySQL version 5.5.41.