2

请我遇到和我在这里发现的一样的问题

MySQL - 从具有相同结构但数据不同的多个表中选择数据

我必须从许多具有相同结构但数据不同的 MySQL 表中选择数据(分成 table_0、table_1、table_2 等到 table_5 以分布数百万条数据记录)。

为每个设备生成数据记录的硬件根据时间戳字段从一个表移动到另一个表,这不是唯一的。例如,table_0 中的 50 条记录可能具有相同的时间戳。当数据到达 table_5 的末尾时,它会返回 table_0 开始覆盖那里的数据。我需要在一个时间范围内获取每个设备上的数据。

每个表的数据列(对于 table_0、table_1... 直到 table_5):
timestamp, robotGroupID, robotID, sensor1, sensor2, sensor3, ... (many of them)

然而,这些表是巨大的,并且 UNION ALL(我读它的速度比 DISTINCT 快)需要永远执行,即使只有两个表,更不用说 6 个了。例如,我将在下面说明两个表。

PHP 中的 MySQL 语句:(仅针对传感器 1、传感器 2 和传感器 3 进行说明)
(SELECT sensor1, sensor2, sensor3 FROM table_0 WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop)
UNION ALL
(SELECT sensor1, sensor2, sensor3 FROM table_1 WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop)

注意,除了表名之外,它是完全相同的查询。机器人在一个时间范围内的传感器数据可能一次跨越一个表、一个表或多个表。

我不能使用 LIMIT,因为无法提前知道每个时间范围内机器人的报告数量。我不能使用 MERGE STORAGE ENGINE 因为我只有对公司数据库的只读访问权限。

我有一个想法,在运行查询之前在每个表上使用 count(robotID) 等进行检查,但我不知道该怎么做,因为我是个新手。

请您认为我如何使 6 个表和更多列的工作更快,因为列数比图示的多得多?提前致谢!

4

3 回答 3

1

字段 RobotID 和 Timestamp 是否已编入索引?

我至少会添加一个(RobotId,timestamp)的多字段索引。

您说您对表具有只读访问权限,那么您可以请求添加此索引吗?我相信它会对您发布的原始查询和更新查询有所帮助。

于 2010-09-03T14:14:17.860 回答
0

我必须承认我仍然是 PHP/MySQL 编码新手,但有很多想法;所以我的代码可能是“脏的”。

所以我以这种方式解决了这个问题以继续前进,但欢迎更好的解决方案。至于任何奇怪的语法,我使用的是基于 PHP PDO 构建的数据库类,因为我在这个项目中使用了许多不同的 RBDMS 类型。

对于 $myQuery_start 变量,我添加了其他列的名称以及传感器 1 到 3。 现在我检查是否需要将 UNION ALL 附加到每个表的查询中。如果下一个表中没有要附加的数据记录,则不需要 UNION ALL。 现在我们建立表查询并组合形成完整的查询 然后连接: 最后执行 $myQuery 以生成所需的所有数据。
$myQuery_start = "(SELECT sensor1, sensor2, sensor3 FROM ";
$myQueryCount_start = "(SELECT COUNT(*) FROM ";
$myQuery_stop = " WHERE robotID=".$robotID." AND timestamp BETWEEN ".$timeStampStart." AND ".$timeStampStop.")";

$count_0 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_0".$myQuery_stop)->fetchColumn();
$count_1 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_1".$myQuery_stop)->fetchColumn();
$count_2 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_2".$myQuery_stop)->fetchColumn();
$count_3 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_3".$myQuery_stop)->fetchColumn();
$count_4 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_4".$myQuery_stop)->fetchColumn();
$count_5 = DB::getDB("mysql", $myDB)->query($myQueryCount_start."table_5".$myQuery_stop)->fetchColumn();


$union_0 = (($count_1 + $count_2 + $count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_1 = (($count_2 + $count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_2 = (($count_3 + $count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_3 = (($count_4 + $count_5) > 0)?" UNION ALL ":"";
$union_4 = (($count_5) > 0)?" UNION ALL ":"";



$query_0 = ($count_0 > 0)?$myQuery_start."ip_minute_stats_0".$myQuery_stop.$union_0:"";
$query_1 = ($count_1 > 0)?$myQuery_start."ip_minute_stats_1".$myQuery_stop.$union_1:"";
$query_2 = ($count_2 > 0)?$myQuery_start."ip_minute_stats_2".$myQuery_stop.$union_2:"";
$query_3 = ($count_3 > 0)?$myQuery_start."ip_minute_stats_3".$myQuery_stop.$union_3:"";
$query_4 = ($count_4 > 0)?$myQuery_start."ip_minute_stats_4".$myQuery_stop.$union_4:"";
$query_5 = ($count_5 > 0)?$myQuery_start."ip_minute_stats_5".$myQuery_stop:"";


$myQuery = $query_0.$query_1.$query_2.$query_3.$query_4.$query_5;

至少这比我以前使用 UNION ALL 的方式快大约 8 倍,所以我认为这是有效的。任何建议的进一步优化?

于 2010-09-03T13:37:21.743 回答
0

If you can convince them to let you change the database structure, you can GREATLY optimize the layout of your database with the help of MySQL Partitioning. You'll want to research "Range Partitioning", and set up partitioning rules that will tell MySQL to automatically sort your data into invisible subtables for way quicker SELECT results. You won't even need multiple tables.

See http://dev.mysql.com/doc/refman/5.1/en/partitioning-overview.html

于 2012-08-15T23:03:08.297 回答