【问题标题】:Best structure for tables with more than 10000 columns超过 10000 列的表的最佳结构
【发布时间】:2012-06-19 23:36:49
【问题描述】:

我正在将一组数据挖掘算法应用于由一组客户以及大量描述性属性组成的数据集,这些属性总结了他们过去行为的各个方面。有 10,000 多个属性,每个属性都存储为以客户 ID 作为主键的表中的一列。由于几个原因,有必要预先计算这些属性,而不是动态计算它们。我通常会尝试选择具有指定属性集的客户。这些算法可以将任意数量的这些属性组合在一个 SELECT 语句中,并连接所需的表。所有表格的行数都相同(每个客户一个)。

我想知道构造这些属性表的最佳方法是什么。将属性分组到 20-30 列的表中更好吗,平均需要更多的连接,但每个 SELECT 的列更少,或者拥有具有最大列数的表以最小化连接数,但可能所有 10K 列都在一次?

我还考虑过使用一个巨大的 3 列 customerID-attribute-value 表并将所有信息存储在那里,但构建一个“选择所有具有我需要的这些属性类型查询的客户”会更难。

我使用的是 MySQL 5.0+,但我认为这是一个一般的 SQL 问题。

【问题讨论】:

  • 为了清楚起见,这些表的主要目的是通过单个 select 语句进行查询,该语句返回满足一组资格(因此属性)的所有客户的 ID,然后加入该到价值表以获得每个客户的价值。
  • 10,000 列太多了。如果您不使用*,SELECT 语句将非常长且混乱。
  • 选择本身是计算机生成的,所以我不太担心它会很长和/或凌乱。
  • 另外,返回给程序的结果数据集只是一列整数(客户 ID)。

标签: mysql sql database normalization


【解决方案1】:

正如@odiszapc 所说,您必须使用元模型结构,例如:

CREATE TABLE customer(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(64));
CREATE TABLE customer_attribute(ID INT NOT NULL, ID_CUSTOMER INT NOT NULL, NAME VARCHAR(64), VALUE VARCHAR(1024));

返回给定客户的基本信息:

SELECT * FROM customers WHERE name='John';

与某些属性匹配的回头客:

SELECT c.* 
FROM customer c 
    INNER JOIN attribute a1 ON a1.id_customer = c.id 
                           AND a1.name = 'address' 
                           AND a1.value = '1078, c/ los gatos madrileños'
    INNER JOIN attribute a2 ON a2.id_customer = c.id 
                           AND a2.name = 'age' 
                           AND a2.value = '27'

您的生成器应该即时生成内部连接。

表上的适当索引应该允许所有这些引擎运行得相对较快(如果我们假设每个客户有 10k 个属性和 10k 个客户,这实际上是一个挑战......)

【讨论】:

  • 这很有趣。我想我可以拥有具有不同数据类型(数字与文本数据)的不同属性表,以允许除了等于或不等于之外进行一些比较。这张表会非常大,10K 属性,数十万客户,最终数百万。我想知道它是否会在桌面服务器上崩溃。
  • 10^4 个属性 x 10^6 个客户是一个非常庞大的数据量。这通常是发生数据库限制并且数据挖掘开始其工作的地方。您应该根据您的某些主要查询的普遍性调查并查看是否无法在夜间(离线批处理)构建某些副本表。
  • 但是,这实际上取决于您的查询、您需要的有关客户的信息类型、每个属性的大小...如果您设法在数据定义中保持简洁,您可能会完全摆脱一个在线系统,具有非常好的硬件和非常好的 dba :D
  • 如果我使用 MEDIUMINT-SMALLINT-TINYINT 数据类型,我想我可以将每个 ID-Attr-Val 压缩成 6 个字节。对于 100K 客户,假设我将其限制为从 5K 属性开始,即 500M 行占用大约 2.79GB?从存储容量来看似乎是合理的,我只是想知道如果您反复加入 500M 行表,即使有索引,性能...也许我只是偏执...
  • 很难说。它是一种遗传算法,可以选择自己的特异性,所以我不想预先将其限制为任意数字。再说一次,我想我读到 MySQL 一次只能将 61 个表连接在一起,所以实际上,60 是任何一次最多的属性。
【解决方案2】:

10,000 列太多了。如果您不使用*,SELECT 语句将非常长且混乱。我认为您可以将属性范围缩小到最有用和最有意义的属性,而消除其他属性

【讨论】:

  • 选择本身是计算机生成的,所以我不太担心它会很长和/或凌乱。我当然希望将属性缩小到一个较小的集合,但我的算法旨在找到许多属性之间的微妙交互,所以我需要首先能够访问它们,这样我才能缩小它们的范围。如果我知道哪些是重要的,我就不需要算法了……
  • 我的意思是可能有一些不那么重要的列,可以忽略,也不会在数据库中存储/表示
【解决方案3】:

根据我的经验,使用具有 10,000 列的表是非常非常非常糟糕的主意。如果将来这个数字会增加怎么办?

如果有很多属性,则不应使用水平缩放的表(具有大量列)。您应该创建一个新表 attributes 并将 alltributes 值放入其中。然后将此表以多对一关系连接到主条目表

也许第二种方法是使用非 SQL(如 MongoDB)系统

【讨论】:

  • 好吧,我正在创建一个新表attributes,但是mysql将它限制为每个表3K列(?),所以它就像attributes1属性2,... 属性N。我想知道在这些多个 attributeN 表之间分配属性的最佳方法。
  • 我对 No-SQL 系统不太熟悉,但我宁愿坚持使用现有的系统,除非另一个选项有巨大的好处。这些不是实时查询,因此速度不是主要考虑因素。
  • 不,表 attrubutes 应该有 3 列:cursomerId、attrName、attrValue。属性彼此相似,它们是行式概念(非列式)
  • 我想到了,但我想知道如何编写 select 语句来返回满足与属性相关的一组条件的所有客户的 id?
猜你喜欢
  • 2010-09-29
  • 2017-09-26
  • 2018-11-26
  • 1970-01-01
  • 2013-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多