【问题标题】:database design decision (NoSQL) [closed]数据库设计决策(NoSQL)[关闭]
【发布时间】:2012-11-09 00:01:21
【问题描述】:

我正在开发具有以下用例的应用程序:

  • 用户上传 csv 文件,这些文件需要在应用程序重启时持久化
  • csv文件中的数据需要查询/排序等
  • 用户在上传文件时指定 csv 文件中的可查询列

目前提出的解决方案是:

  • 对于小文件(更常见),将数据转换为 xml 并将其存储为 LOB 或文件系统中。对于查询,将整个数据吞入内存并使用 XQuery 之类的东西
  • 对于较大的文件,在数据库 (MySQL) 中创建动态表,并在可查询列上创建索引

尽管我们已经对该解决方案进行了原型设计,并且效果相当不错,但它使我们无法支持更复杂的文件格式,例如 XML 和 JSON。该解决方案还有一些更琐碎的问题,我不会讨论。

考虑到 NoSQL 数据库的无模式特性,我认为它们可以用来解决这个问题。不过,我没有使用 NoSQL 的实际经验。我的问题是:

  1. NoSQL 是否非常适合此用例?
  2. 如果有,是哪个 NoSQL 数据库?
  3. 我们如何将 csv 文件存储在数据库中(列标题构成键,每行的数据字段构成值的键值对集合?)
  4. 我们如何存储可能具有深度层次结构的 XML/JSON 文件?
  5. 查询/索引和其他性能考虑如何?这与 MySQL 之类的相比如何?

感谢您的回复并提前致谢!

示例 csv 文件:

employee_id,name,address  
1234,XXXX,abcabc  
001001,YYY,xyzxyz  
...  

DDL 语句:

CREATE TABLE `employees`(  
  `id` INT(6) NOT NULL AUTO_INCREMENT,  
  `employee_id` VARCHAR(12) NOT NULL,  
  `name` VARCHAR(255),  
  `address` TEXT,  
  PRIMARY KEY (`id`),  
  UNIQUE INDEX `EMPLOYEE_ID` (`employee_id`)  
);  

对于 csv 文件中的每一行

INSERT INTO `employees`  
                (`employee_id`,  
                 `name`,  
                 `address`)  
       VALUES (...);  

【问题讨论】:

    标签: nosql


    【解决方案1】:

    不是一个完整的答案,但我想我可以在某些方面提供帮助。

    对于第 2 点,我至少可以提供this link,这有助于整理 NoSQL 实现。

    对于数字 3,使用 SQL 数据库(但也应该适合 NoSQL 系统),我会将每一列和每一行表示为单独的表,并添加带有外键的第三个表到列和行,以及单元格的值。您会得到一个易于过滤的大表。

    对于数字 4,您需要“在表格中表示分层数据”

    解决这个问题的常用方法是有一个带有属性的表,以及同一个表的外键,指向父表,例如:

    +----+------------+------------+--------+
    | id | attribute1 | attribute2 | parent |
    +----+------------+------------+--------+
    |  0 | potato     | berliner   | NULL   |
    | 1  | hello      | jack       | 0      |
    | 2  | hello      | frank      | 0      |
    | 3  | die        | please     | 1      |
    |  4 | no         | thanks     | 1      |
    |  5 | okay       | man        | 4      |
    |  6 | no         | ideas      | 2      |
    |  7 | last       | one        | 2      |
    +----+------------+------------+--------+
    

    现在的问题是,如果您想从元素 1 中获取所有子元素,则必须单独查询每个项目以获取其子元素。其他一些操作很困难,因为它们需要获取到对象的路径、遍历许多其他对象并进行额外的数据查询。

    一种常见的解决方法,也是我使用和喜欢的一种,称为修改的预排序树遍历

    使用这种技术,我们需要在数据存储和应用程序之间增加一个额外的层,以便在每次结构更改修改时填充一些额外的列。我们将为每个对象分配三个属性:leftrightdepth

    leftright 属性将被填充,从顶部开始计数每个对象,递归遍历所有树叶。

    这是leftright的遍历算法的模糊近似(depth的部分很容易猜测,这只是要添加的几行):

    1. 设置树根(如果有很多则设置第一个树根)left 属性为 1
    2. 转到它的第一个(或下一个)孩子。将其left 属性设置为 最后一个数字加一(这里是 2)
    3. 它有孩子吗?如果是,返回数字 2。如果不是,将其 right 设置为最后一个数字加一。
    4. 转到下一个孩子,并执行与 2 相同的操作
    5. 如果没有更多的孩子,转到父母的下一个孩子并执行与 2 中相同的操作

    这是一张解释我们得到的结果的图片:


    (来源:narod.ru

    现在找到一个对象的所有后代或它的所有祖先真的很容易。这可以通过使用leftright 的单个查询来完成。

    使用它时重要的是在数据和应用程序之间实现良好的层,处理leftrightdepth 属性。在以下情况下必须调整这些字段:

    • 一个对象被删除
    • 添加了一个对象
    • 对象的parent字段被修改

    这可以通过使用锁的并行进程来完成。也可以直接在数据和应用之间实现。

    有关树木的更多信息,请参阅这些链接:

    我个人在使用 NoSQL 的几次 django-nonrel 和 django-mptt 方面取得了不错的成绩。

    【讨论】:

    • 感谢您的帮助。我倾向于给定here 的闭包表概念。我希望有一个更简单的基于 NoSQL 的解决方案,但我想我现在会坚持使用 SQL。我不确定我是否理解第三个问题的观点。您能解释一下这种方法与我目前所做的相比有什么优势吗?
    • 你现在在做什么? “键值对的集合,其中列标题构成键,每行的数据字段构成值”?在数据字段中存储这么多元素并不是数据库的好用处。数据库必须适合数据,而不是数据适合数据库。
    • 我目前正在做的是“对于较大的文件,在数据库 (MySQL) 中创建动态表,并在可查询列上创建索引”。这是最好的方法吗?
    • 我不太明白您所说的“创建动态表”是什么意思。我不会区分小文件和大文件,我会将所有数据放入数据库中,使用 4 个表: CSVFile(带有 CSVFile 的外键和一个布尔字段“可查询”); (带有CSVFile的外键); 单元格(外键指向行,外键指向列)这会生成一些大表,但您会获得一致的数据架构并使用适当优化的 SQL 查询和过程,您应该不会有任何问题。
    • “创建动态表”是指每次上传 csv 文件时,我都会从我的应用程序发出一个 DDL 语句,该语句会创建一个表来保存 csv 文件中的数据。该表将包含 csv 文件所做的所有列,以及可查询列的索引。我意识到这不会像您的建议那样为我提供一致的架构,但就性能而言,哪种方式更好?
    猜你喜欢
    • 2015-04-16
    • 2012-12-08
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    相关资源
    最近更新 更多