【问题标题】:Joining across 3000+ tables加入超过 3000 个表
【发布时间】:2014-09-17 13:30:27
【问题描述】:

好的,这里有点奇怪

我有一个客户数据数据库。我的客户是拥有自己客户的企业。

我有 3000 个表格(每个企业一个),每个表格中有数千个电子邮件地址。每个表都一样,保存名称。

我需要找到一种方法来查找电子邮件在企业之间的交叉位置(即出现在多个表格中)以及它们所在的表格的名称。

我尝试将所有条目和表名整理到一个表中并使用“分组依据”,但数据量太大而无法在我们的服务器不崩溃的情况下运行它...

有没有人建议如何在不运行 3000 组连接的情况下完成此操作?

另外,我根本无法更改数据结构。

谢谢

编辑:为了响应那些“有用的”重组 cmets,不是我的数据库,不是我的系统,我几个月前才开始分析数据

【问题讨论】:

  • 有人有建议吗 是的!停止为企业制作桌子。使用一个表!
  • 为什么要加入这些表?听起来好像你真的想要UNION 甚至UNION ALL
  • 找到设计这个怪物的人,打他们的头。其次告诉管理层这个结构必须改变,因为它完全是愚蠢的。第三,如果管理层拒绝,那就找一份新工作,因为这个人不可能给你足够的薪水来忍受这种无能的程度。
  • Each table is identical, save the name. 然后合并表并添加name 字段(或外键)。问题解决了。
  • 这种愚蠢的设计助长了“JOINS BAD!!! NOSQL GOOOOD!!!”的荒谬概念当 RDBMS 成为开发人员手中的工具而毫无头绪时,我想它是没有机会的。

标签: mysql sql


【解决方案1】:

相同结构的多个表几乎没有意义,只需要一个business 字段来修复这个结构。如果可能的话,你应该修复结构。如果它被强加给你并且你无法改变它,你应该仍然可以使用它。

从每个表格中选择不同的电子邮件和表格名称UNION ALL 或将它们拉入新表格,然后使用GROUP BYHAVING 查找包含多个表格的电子邮件。

SELECT email
FROM Combined_Table
GROUP BY email
HAVING COUNT(sourc_table) > 1

【讨论】:

  • 将所有数据插入到一张表中,使用上面的查询。
  • 谢谢,这是我最初使用的。可悲的是,服务器无法处理海量数据集
  • @JohnHC 你试过UNION他们吗?如果您逐个表格将不同的电子邮件插入到一个新表格中,这应该不会那么繁重。
  • @JohnHC 。 . .如果单表解决方案一开始不起作用,则说明您采用了错误的方法来修复它。首先想到的两件事是索引表和使用多个分区进行存储。打破桌子是最后的手段,通常只是出于安全原因。
【解决方案2】:

所以,你说你不能改变数据结构,但你也许可以提供兼容的升级。

  1. 提供一个新的巨型表:

     CREATE TABLE business_email (
         id_business INT(10) NOT NULL,
         email VARCHAR(255) NOT NULL UNIQUE,
         PRIMARY KEY id_business, email
     ) ENGINE = MYISAM;
    

Myisam 引擎,因此您不必担心交易。

  1. 为每个业务表添加触发器以将电子邮件复制到新表中:

    DELIMITER \\
    
    CREATE TRIGGER TRG_COPY_EMAIL_BUSINESS1 AFTER INSERT OR UPDATE ON business1 FOR EACH ROW 
    BEGIN
        INSERT INTO `business_email` (`id_business`, `email`) VALUES (NEW.`id_business`, NEW.`email`) ON DUPLICATE KEY UPDATE `id_business`=NEW.`id_business`;
    END;
    \\
    
    DELIMITER ;
    

您的问题是在创建新表时动态添加它。这应该不是问题,因为您的应用程序代码中显然已经存在动态 DDL。

  1. 将所有现有数据复制到新表中:

    INSERT INTO `business_email` (`id_business`, `email`) 
    SELECT email FROM business1
    UNION
    SELECT email FROM business2
    ...
    ;
    
    COMMIT;
    
  2. 继续查询新的business_email 表,这应该大大简化:

    SELECT `id_business` FROM `business_email` 
    WHERE
    GROUP BY `email`
    HAVING COUNT(`email`) > 2;
    

这个查询应该很容易处理。如果不是,请详细说明问题,因为我认为即使对于数百万行,正确索引的表也不应该是一个问题(我不相信是这种情况,因为我们谈论的是电子邮件)

此解决方案的优势在于您始终保持最新状态,而无需更改应用程序的工作方式。您只需添加另一层即可提供额外的业务价值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-07
    • 2021-12-31
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 2021-02-23
    相关资源
    最近更新 更多