Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 存储行数和行数以加快分页是一个坏主意吗?_Mysql_Pagination - Fatal编程技术网

Mysql 存储行数和行数以加快分页是一个坏主意吗?

Mysql 存储行数和行数以加快分页是一个坏主意吗?,mysql,pagination,Mysql,Pagination,我的网站有超过20.000.000个条目,条目有类别(FK)和标签(M2M)。对于查询,甚至像selectid-fromtableorderbyid-limit1000000,10MySQL需要扫描1000010行,但速度太慢了,令人无法接受(而pks、索引、连接等在这里帮助不大,仍然是1000010行)。因此,我试图通过使用以下触发器存储行计数和行号来加速分页: DELIMITER // CREATE TRIGGER @trigger_name AFTER INSERT ON entry_ta

我的网站有超过20.000.000个条目,条目有类别(FK)和标签(M2M)。对于查询,甚至像
selectid-fromtableorderbyid-limit1000000,10
MySQL需要扫描1000010行,但速度太慢了,令人无法接受(而pks、索引、连接等在这里帮助不大,仍然是1000010行)。因此,我试图通过使用以下触发器存储行计数和行号来加速分页:

DELIMITER //
CREATE TRIGGER @trigger_name
AFTER INSERT
ON entry_table FOR EACH ROW
BEGIN
    UPDATE category_table SET row_count = (@rc := row_count + 1)
    WHERE id = NEW.category_id;
    NEW.row_number_in_category = @rc;
END //
然后我可以简单地:

SELECT * 
FROM entry_table 
WHERE row_number_in_category > 10 
ORDER BY row_number_in_category 
LIMIT 10
(现在只扫描了10行,因此选择的速度非常快,虽然插入速度较慢,但与选择相比,插入的速度非常罕见,所以这是正常的)


这是一种不好的方法吗?有好的替代方法吗?

尽管我喜欢这个问题的解决方案。如果entry_表中的数据随着时间的推移发生更改(可能被删除或分配到不同的类别),则可能会出现一些问题

它还限制了数据的排序方式,该方法假定数据仅按插入顺序排序。覆盖多个排序方法需要额外的触发器和摘要数据

分页的另一种方法是将要排序/分页的字段的偏移量传递给limit参数,而不是传递给limit参数的偏移量

与此相反:

SELECT id FROM table ORDER BY id LIMIT 1000000, 10
执行此操作-在此场景中,假设上次查看的结果的id为1000000

SELECT id FROM table WHERE id > 1000000 ORDER BY id LIMIT 0, 10
通过跟踪分页的偏移量,可以将其传递给后续的数据查询,并避免对永远不会成为最终结果一部分的行进行数据库排序

如果您真的只想要2000万行中的10行,那么您可以进一步猜测,接下来的10行匹配将出现在接下来的1000个总体结果中。如果不是这样的话,也许需要一些逻辑,以更大的余量重复查询

SELECT id FROM table WHERE id BETWEEN 1000000 AND 1001000 ORDER BY id LIMIT 0, 10

这应该要快得多,因为排序可能会将结果限制在一次传递中。

对我来说,这听起来是一个很酷的优化;如果您已经排除了所有其他的PARF原因(例如索引),这种非正规化是可以接受的,尽管考虑将这些信息存储在一个单独的元数据表中,以保持您的主模式“干净”。这是一个好主意,但它可能不是必需的,因为不像PostgreSQL MySQL处理选择计数(*)。非常适合索引表。有关更多详细信息,请参见我的答案。如果
id
未编入索引,则只需扫描这些行。你解决了一个错误的问题。这些条目会被删除吗?或者一旦被插入,它们会永远在那里吗?我觉得这样做不管用。选择项不需要包括类别id以及类别中的行编号吗?值得指出的是,除非id都是连续的并且从1开始,
LIMIT 1000000,10
id>1000000不同。。。限制为0,10
@Arth,谢谢,是的,没错。虽然这个原理是有效的,但示例中的两个查询可能不会返回与您所说的相同的结果。很好的澄清。