【问题标题】:MySQL SELECT from a group of tables retrieved from INFORMATION_SCHEMA从 INFORMATION_SCHEMA 检索到的一组表中的 MySQL SELECT
【发布时间】:2010-10-10 20:18:20
【问题描述】:

大家好。我有以下一组可变的表格,每天都会累加:

data-2010-10-10
data-2010-10-11
data-2010-10-12
data-2010-10-13

等等。所有表都具有相同的结构,我想做的是一次从所有表中选择内容。因为我正在运行 InnoDB,所以我无法使用 MERGE 表。无论如何,我使用以下语句从我的 information_schema 中选择表名:

select table_name from `information_schema`.`tables` 
  where `table_schema` = 'mydb2' and `table_name` like 'data-%'

返回我想合并的所有表格。我还可以对返回的结果进行 group_concat 以获取以逗号作为分隔符的列表。现在我陷入困境的是运行一个选择查询,该查询实际上会从这些表中检索数据。

感谢任何提示。谢谢! 〜K

【问题讨论】:

标签: sql mysql innodb


【解决方案1】:

您必须使用动态 SQL 来构建查询(或多个查询)以从这些表中获取结果。也就是说,您从 information_schema 查询中获取表作为字符串,然后将这些字符串插入到进一步的查询中。

涉及对所有表的单个查询的 UNION:

SELECT ...
FROM (SELECT * FROM `data-2010-10-10`
      UNION ALL SELECT * FROM `data-2010-10-11`
      UNION ALL SELECT * FROM `data-2010-10-12`
      UNION ALL SELECT * FROM `data-2010-10-13`) AS u

但我质疑您每天创建单独表格的设计。起初看起来很方便,但表的传播失控,最终您很难进行普通查询,就像您现在面临的困难一样。这是一个antipattern,我称之为Metadata Tribbles

您的数据可能会存储在一个表中,并带有一个日期列,可让您区分不同日期的数据。您可能只需要创建索引来协助您针对总数据运行的查询。


你的评论:

您不能在 SQL 查询(包括视图定义)中使表名动态化。您可以将表名插入字符串,然后将该字符串准备为 SQL 查询。

您可以使用CONCAT() 函数构建一个字符串,然后使用PREPARE and EXECUTE 将该字符串作为查询运行。但是由于 mysql 客户端中没有循环结构,如果您不能用 Python 或 PHP 或类似的宿主语言编写脚本,则必须编写存储过程来执行此操作。

【讨论】:

  • 感谢您的回答比尔。是的,如果查询是从 python/php 内部运行的,Unions 会很好,但我真的很想在 MySQL 级别获得它,也许在 View 中。我实际上是按月而不是按天将数据分布在不同的表中,而是按天进行测试和基准测试。我可以接受很多这样的表格,因为它们会被归档并每月查询一次以获取统计信息。每个表将包含约 2 百万行,活动(当前)表将每 30 秒更新一次(随机 IO)。
  • 而且,在 5.6 之后,您将对该表进行分区。
  • @PaulCampbell,分区不是必需的,而且在比许多人想象的要少的情况下有用。
  • @BillKarwin 我同意您关于使用单个表的观点,然后在该单个表上的查询开始拖拽并且用户正在寻找一种轻松的方式修剪数百万条记录以加快速度。也许我应该说“你可能”而不是“你会”。
  • @BillKarwin 是的,这取决于查询的性质、索引的有用性、系统资源的可用性以及一大堆其他因素和用例。现在我要去看看能不能找到你的书。
猜你喜欢
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2020-01-17
  • 2020-12-14
相关资源
最近更新 更多