Mysql 如何在另一个表中存储*排序*选择结果?
在我的项目中,我经常需要将SELECT的结果存储在另一个表中,我们称之为resultset。原因是在web应用程序中动态显示大量行,同时根据需要仅加载小块 通常,这是通过以下查询完成的:Mysql 如何在另一个表中存储*排序*选择结果?,mysql,sql,innodb,Mysql,Sql,Innodb,在我的项目中,我经常需要将SELECT的结果存储在另一个表中,我们称之为resultset。原因是在web应用程序中动态显示大量行,同时根据需要仅加载小块 通常,这是通过以下查询完成的: SET @counter := 0; INSERT INTO resultsetdata SELECT "12345", @counter:=@counter+1, a.ID FROM sometable a JOIN bigtable b WHERE (a.foo = b.ba
SET @counter := 0;
INSERT INTO resultsetdata
SELECT "12345", @counter:=@counter+1, a.ID
FROM sometable a
JOIN bigtable b
WHERE (a.foo = b.bar)
ORDER BY a.whatever DESC;
固定的12345值只是一个值,用于标识作为一个整体的结果集以及每个查询的更改。第二列是递增索引计数器,用于允许直接访问结果中的特定行,ID列引用源数据表中的特定行
当应用程序需要一定范围的结果时,我只需将resultsetdata与源表连接以获取详细数据-这与上面的resultsetdata查询相对,后者可能需要2-3秒才能完成,这解释了我为什么需要这个中间表
SELECT查询本身与此问题无关
resultsetdata具有以下结构:
CREATE TABLE `resultsetdata` (
`ID` int(11) NOT NULL,
`ContIdx` int(11) NOT NULL,
`Value` int(11) NOT NULL,
PRIMARY KEY (`ID`,`ContIdx`)
) ENGINE=InnoDB;
这通常像一个符咒,但最近我们注意到,在某些情况下,结果的顺序是不正确的。这取决于查询本身,例如,添加DISTINCT是一个典型的原因,服务器版本和源表中包含的数据,因此我想可以说,使用这种方法行顺序是不可预测的。这可能取决于内部优化
然而,现在的问题是,我想不出任何能给我带来预期结果的替代方案
由于resultset可以获得数千行,因此在内存中加载所有数据然后手动插入是不可行的
有什么建议吗
编辑:如需进一步澄清,请查看以下查询:
DROP TABLE IF EXISTS test;
CREATE TABLE test (ID INT NOT NULL, PRIMARY KEY(ID)) ENGINE=InnoDB;
INSERT INTO test (ID) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
SET @counter:=0;
SELECT "12345", @counter:=@counter+1, ID
FROM test
ORDER BY ID DESC;
这将产生预期的以下结果:
+-------+----------------------+----+
| 12345 | @counter:=@counter+1 | ID |
+-------+----------------------+----+
| 12345 | 1 | 10 |
| 12345 | 2 | 9 |
| 12345 | 3 | 8 |
| 12345 | 4 | 7 |
| 12345 | 5 | 6 |
| 12345 | 6 | 5 |
| 12345 | 7 | 4 |
| 12345 | 8 | 3 |
| 12345 | 9 | 2 |
| 12345 | 10 | 1 |
+-------+----------------------+----+
10 rows in set (0.00 sec)
如前所述,在某些情况下,我无法在此提供测试用例,很抱歉,这可能会导致类似的结果:
+-------+----------------------+----+
| 12345 | @counter:=@counter+1 | ID |
+-------+----------------------+----+
| 12345 | 10 | 10 |
| 12345 | 9 | 9 |
| 12345 | 8 | 8 |
| 12345 | 7 | 7 |
| 12345 | 6 | 6 |
| 12345 | 5 | 5 |
| 12345 | 4 | 4 |
| 12345 | 3 | 3 |
| 12345 | 2 | 2 |
| 12345 | 1 | 1 |
+-------+----------------------+----+
我并不是说这是一个MySQL错误,我完全理解我的方法目前提供了不可预测的结果。不过,我不知道如何调整它以获得可预测的结果。这是因为插入记录时的排序顺序与检索记录时的顺序无关 检索它们时,将创建一个查询计划。如果SELECT语句中未指定ORDER BY,则订单将取决于生成的查询计划。这就是为什么它是不可预测的,添加DISTINCT可以改变顺序
解决方案是存储足够的数据,以便使用ORDERBY子句以正确的顺序检索它们。在您的情况下,您已通过a.whatever对数据进行排序。a.任何内容都可以存储在resultsetdata中吗?如果是这样,则可以按正确的顺序读取记录。这是因为插入记录时的排序顺序与检索记录时的顺序无关 检索它们时,将创建一个查询计划。如果SELECT语句中未指定ORDER BY,则订单将取决于生成的查询计划。这就是为什么它是不可预测的,添加DISTINCT可以改变顺序
解决方案是存储足够的数据,以便使用ORDERBY子句以正确的顺序检索它们。在您的情况下,您已通过a.whatever对数据进行排序。a.任何内容都可以存储在resultsetdata中吗?如果是这样,那么您可以按正确的顺序读取记录。也许您可以将select包装成另一个select:
SET @counter := 0;
INSERT INTO resultsetdata
SELECT *, @counter := @counter + 1
FROM (
SELECT "12345", a.ID
FROM sometable a
JOIN bigtable b
WHERE a.foo = b.bar
ORDER BY a.whatever DESC
) AS tmp
。。。但你仍然任由MySQL优化器的愚蠢摆布
这就是我对这个话题的所有发现,但我找不到一个可靠的保证:
也许您可以将选择包装成另一个选择:
SET @counter := 0;
INSERT INTO resultsetdata
SELECT *, @counter := @counter + 1
FROM (
SELECT "12345", a.ID
FROM sometable a
JOIN bigtable b
WHERE a.foo = b.bar
ORDER BY a.whatever DESC
) AS tmp
。。。但你仍然任由MySQL优化器的愚蠢摆布
这就是我对这个话题的所有发现,但我找不到一个可靠的保证:
订单怎么不正确?如中所示,最终的“id”没有按您希望的方式排序?您已经添加了一个计数器,您的意思是该计数器没有正确排序吗?如何选择,在该计数器上进行排序?总之,总的来说,这整件事感觉有点像一个手动实现的缓存系统。你确定你需要这个方法吗?您能否更快地将结果保存到某种真正的缓存系统中,或者更新sometable和bigtable,这样就不会花费那么多秒?您能否提供正确排序的结果和错误排序的结果?我的意思是,在某些情况下,当在控制台上执行SELECT而不执行INSERT INTO时,您会看到ContIdx按降序排列。是的,这在某种程度上与缓存系统有关,但我不认为将大量数据加载到内存中是更好的解决方案。这个问题适用于包含大量已获取数据的各种查询/表,因此我无法进一步优化SELECT查询,也就是说,当用户浏览数据时,我无法一次又一次地进行优化。此外,我需要一些东西
因为表中不断地填充着数据。这就是关系数据库的工作原理。表中的行未排序,请将它们想象成篮子中的球。确保特定顺序的唯一方法是使用order by。@hyЛö:添加了@a_horse_,其名称为“correct”,但可以使用唯一的递增索引来存储行的顺序,在我的例子中,该索引将为ContIdx。顺序如何不正确?如中所示,最终的“id”没有按您希望的方式排序?您已经添加了一个计数器,您的意思是该计数器没有正确排序吗?如何选择,在该计数器上进行排序?总之,总的来说,这整件事感觉有点像一个手动实现的缓存系统。你确定你需要这个方法吗?您能否更快地将结果保存到某种真正的缓存系统中,或者更新sometable和bigtable,这样就不会花费那么多秒?您能否提供正确排序的结果和错误排序的结果?我的意思是,在某些情况下,当在控制台上执行SELECT而不执行INSERT INTO时,您会看到ContIdx按降序排列。是的,这在某种程度上与缓存系统有关,但我不认为将大量数据加载到内存中是更好的解决方案。这个问题适用于包含大量已获取数据的各种查询/表,因此我无法进一步优化SELECT查询,也就是说,当用户浏览数据时,我无法一次又一次地进行优化。此外,我需要一些静态的东西,因为表中不断地填充着数据。这就是关系数据库的工作方式。表中的行未排序,请将它们想象成篮子中的球。确保特定顺序的唯一方法是使用order by。@hyЛö:添加了@a_horse_,其名称为“no_name:correct”,但可以使用唯一的递增索引来存储行的顺序,在我的例子中,该索引是ContIdx。不幸的是,否,我无法在resultsetdata中存储a.whatever,因为我也可能在多个列上使用ORDER BY,并且排序列的类型并不总是相同的。除此之外,这是一个框架的一部分,它甚至不知道真正的查询是关于什么的。不幸的是,不,我不能在resultsetdata中存储a.whatever,因为我也可能在多个列上使用ORDER BY,并且排序列的类型并不总是相同的。除此之外,这是一个框架的一部分,它甚至不知道真正的查询是关于什么的。棒极了:-我不希望优化器会尝试优化外部选择,尽管祈求好运。也许你应该从真正的专家那里找到一些解释,比如Quassnoi@or的旧博客,或者你发现的任何东西:简单而且有效。棒极了:-我不希望优化器会尝试优化外部选择,尽管祈求好运。也许你应该从真正的专家那里找到一些解释,比如Quassnoi@or的旧博客,或者你找到的任何东西: