我需要在PHP和Mysql中处理分页,问题陈述如下:
我有一个表,其中包含 2 个外键关系的数十万条记录,例如“用户”和“项目”,并且该表经常更改,为特定用户添加或删除项目。现在我想向用户列出所有项目,并在标题中显示分页和总数。我的表是 MyISAM 并且也使用 SQL_CALC_FOUND_ROWS。表结构如下,基数很大。
CREATE TABLE `USER_ITEMS` (
`ID` int(11) NOT NULL,
`ITEMS` int(11) unsigned NOT NULL DEFAULT '0',
`USER` int(11) unsigned NOT NULL DEFAULT '0',
`TYPE` char(1) NOT NULL DEFAULT '',
`TIME` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`SEEN` char(1) NOT NULL,
`FILTERED` char(1) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `IND1` (`USER`,`ITEMS`),
KEY `USER` (`USER`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
我试过的解决方案:
- 我对所有分页使用限制在 Mysql 上执行选择,但是如果实时删除,我们会得到重复的项目,或者如果在分页时添加任何项目,我们会得到丢失的项目。而且很多时候,由于排序方式和其他原因,查询速度非常慢条件领先的业绩受到打击。这是带有 where、order by 和 limit 的简单 Select 查询。
- 我使用 Memcache 存储他查看过的页面的项目,并在分页期间获取不包括 Memcache 中的项目的项目,但这也会导致查询速度变慢。这是 Select query with where with ITEMS NOT IN , order by and limit .
问题主要是数据的准确性、查询执行时间和网络阻塞方面的性能、php 内存耗尽。
我想知道这些是否是相同的一般做法,或者我们是否有针对此类场景的更好的实现/引擎/缓存。
最佳答案
为了不丢失/重复条目的分页,您需要“记住您离开的地方”而不是使用 OFFSET
。
也就是对于“下一个”页面,做
WHERE id > $last
ORDER BY id
LIMIT 10
然后保留 [下一步] 按钮的最后一个 ID。 (由于您没有提供您的代码,我不能更具体。)
更多详情见my pagination blog .
INDEX(user)
是多余的,因为您有 UNIQUE(user, items)
。
考虑删除 id
,因为唯一 key 可以提升为 PK。要遍历复合键,请参阅 another blog .
关于php - 在 php 和 mysql 大表中更改数据的分页?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35479889/