坦克到每个身体。你的回答对我帮助很大。我认为现在我找到了更好的解决方案。
这个问题涉及两个关键问题:
为了在大表上进行有效的分页,我通过在表上进行先前更新找到了解决方案,但这样做我遇到了更新所需的 51 分钟时间问题,因此我的 java 基础架构超时(spring-批处理步骤)。
现在在您的帮助下,我找到了两种在大表上分页的解决方案,以及一种更新大表的解决方案。
为了达到这个性能,服务器需要内存。我在使用 32 GB 内存的开发服务器上尝试此解决方案。
常见的解决步骤
要按照我需要的字段 tupla 进行分页,我已经创建了一个索引:
KEY `hotel_id_idImageType` (`hotel_id`,`idImageType`)
要实现新的解决方案,我们必须通过将主键部分添加到索引尾部KEY hotel_id_idImageType (hotel_id,idImageType, primary key fields)来更改此索引:
drop index hotel_id_idImageType on images;
create index hotelTypePhoto on images (hotel_id, idImageType, photo_id);
这是避免触摸表并仅使用索引文件所必需的...
假设我们想要 19000000 条记录之后的 10 条记录。
这个答案中的小数点是,
解决方案 1
此解决方案非常实用,不需要额外的字段orderid,并且您不必在分页之前进行任何更新:
select * from images im inner join
(select photo_id from images
order by hotel_id, idImageType, photo_id
limit 19000000,10) k
on im.photo_id = k.photo_id;
在我的 2100 万表记录上创建表 k 只需要 1.5 秒,因为它只使用索引 hotelTypePhoto 中的三个字段,所以还没有访问表文件并仅处理索引文件。
订单与原始所需的 (hotel_id, idImageType) 一样,因为包含在 (hotel_id, idImageType, photo_id):同一个子集...
加入不需要时间,因此每次在同一页面上执行分页只需要 1.5 秒,如果您必须在 3 个月内分批执行,这是一个好时机。
在使用 4 GB 内存的生产服务器上,相同的查询需要 3.5 秒。
对表进行分区无助于提高性能。
如果服务器将其放入缓存中,时间会减少,或者如果您执行 jdbc 参数声明,时间也会减少(我想)。
如果你必须经常使用它,它的优点是它不关心数据是否发生变化。
解决方案 2
这个方案需要额外的字段orderid,并且需要批量导入更新一次orderid,直到下一次批量导入数据才可以改变。
然后你可以在 0000 秒内对表格进行分页。
set @orderid = 0;
update images im inner join (
select photo_id, (@orderid := @orderid + 1) as newOrder
from images order by hotel_id, idImageType, photo_id
) k
on im.photo_id = k.photo_id
set im.orderid = k.newOrder;
表 k 几乎和第一个解决方案一样快。
所有更新只需要 150,551 秒,比 51 分钟要好得多!!! (150s vs 3060s)
在批量更新后,您可以通过以下方式进行分页:
select * from images im where orderid between 19000000 and 19000010;
或更好
select * from images im where orderid >= 19000000 and orderid< 19000010;
这需要 0,000 秒来执行第一次和所有其他时间。
Rick 评论后编辑
解决方案 3
此解决方案是为了避免使用额外的字段和偏移量。但也需要像this solution中那样记住最后一页的读取
这是一种快速的解决方案,仅使用 4GB 内存即可用于在线服务器生产
假设您需要读取 20000000 之后的最后十条记录。
有两种情况需要注意:
- 如果您像我一样需要全部内容,可以从第一页开始读取到 20000000,并更新一些变量以记录最后一页读取的内容。
- 您只需要读取 20000000 之后的最后 10 个。
在第二种情况下,您必须进行预查询才能找到起始页:
select hotel_id, idImageType, photo_id
from images im
order by hotel_id, idImageType, photo_id limit 20000000,1
它给了我:
+----------+-------------+----------+
| hotel_id | idImageType | photo_id |
+----------+-------------+----------+
| 1309878 | 4 | 43259857 |
+----------+-------------+----------+
这需要 6.73 秒。
因此,您可以将此值存储在变量中以供下次使用。
假设我们命名为@hot=1309878, @type=4, @photo=43259857
然后你可以像这样在第二个查询中使用它:
select * from images im
where
hotel_id>@hot OR (
hotel_id=@hot and idImageType>@type OR (
idImageType=@type and photo_id>@photo
)
)
order by hotel_id, idImageType, photo_id limit 10;
第一个子句hotel_id>@hot 获取滚动索引上实际第一个字段之后的所有记录,但丢失了一些记录。要获取它,我们必须执行 OR 子句,该子句将第一个索引字段全部保留为未读记录。
现在只需 0.10 秒。
但是这个查询可以优化(布尔分布):
select * from images im
where
hotel_id>@hot OR (
hotel_id=@hot and
(idImageType>@type or idImageType=@type)
and (idImageType>@type or photo_id>@photo
)
)
order by hotel_id, idImageType, photo_id limit 10;
变成:
select * from images im
where
hotel_id>@hot OR (
hotel_id=@hot and
idImageType>=@type
and (idImageType>@type or photo_id>@photo
)
)
order by hotel_id, idImageType, photo_id limit 10;
变成:
select * from images im
where
(hotel_id>@hot OR hotel_id=@hot) and
(hotel_id>@hot OR
(idImageType>=@type and (idImageType>@type or photo_id>@photo))
)
order by hotel_id, idImageType, photo_id limit 10;
变成:
select * from images im
where
hotel_id>=@hot and
(hotel_id>@hot OR
(idImageType>=@type and (idImageType>@type or photo_id>@photo))
)
order by hotel_id, idImageType, photo_id limit 10;
它们是我们可以通过限制获得的相同数据吗?
要快速不详尽测试:
select im.* from images im inner join (
select photo_id from images order by hotel_id, idImageType, photo_id limit 20000000,10
) k
on im.photo_id=k.photo_id
order by im.hotel_id, im.idImageType, im.photo_id;
这需要 6.56 秒,数据与上面的查询相同。
所以测试是阳性的。
在此解决方案中,您只需要在第一次需要在第一页上寻找阅读时花费 6.73 秒(但如果您需要所有内容,则不需要)。
要真正的所有其他页面,您只需要 0.10 秒即可获得非常好的结果。
感谢 rick 对基于存储最后一页读取的解决方案的提示。
结论
在解决方案 1 上,您没有任何额外的字段,每页需要 3.5 秒
在解决方案 2 上,您有额外的字段,需要一个大内存服务器(测试 32 GB)在 150 秒内。但是您在 0,000 秒内阅读了该页面。
在解决方案 3 上,您没有任何额外的字段,但必须存储最后一页读取指针,如果您没有从第一页开始阅读,则必须花费 6,73第一页秒。然后你在所有其他页面上只花费 0.10 秒。
最好的问候
编辑 3
解决方案 3 正是 Rick 所建议的。对不起,在我之前的解决方案 3 中我犯了一个错误,当我编写了正确的解决方案时,我应用了一些布尔规则,如分配属性等,之后所有我得到相同的丰富解决方案!
问候