需要的数据库建议 - > Columnar,Embedded(如果可能)

Mat*_*olf 9 c# sql database api concurrency

编辑:作为答案的结果到目前为止,我希望在我喜欢的内容中添加更多关注点:允许在内存中编写的数据库(可能是简单的C#代码),并且存储选项具有持久性以便访问数据从R. Redis到目前为止看起来最有希望.我还考虑实际使用类似于Lockfree ++或ZeroMQ的东西,以避免将数据同时写入数据库,而是通过消息总线/其他实现将所有数据发送到持久化数据,并让一个"actor"处理所有写操作内存数据库或其他解决方案.除了Redis之外还有更多的想法(有些人提到了SQLite,我还需要测试它的性能).还有其他建议吗?

我正在寻找满足我下面大部分要求的理想数据库结构/解决方案,但到目前为止我完全失败了.你能帮忙吗?

我的任务:我在.Net 4.5(C#)中运行一个进程并生成(通常)我希望在其他应用程序中进行进一步分析的值类型,因此要么保留内存,要么保留在磁盘上.更多下面.数据在不同的任务/线程内生成,因此基于行的数据格式不能很好地匹配这种情况(因为在不同的线程中生成的数据是在不同的时间生成的,因此不对齐).因此我认为柱状数据结构可能是合适的,但如果我错了,请纠正我.

例:

任务/线程#1在给定时间戳处生成以下数据

datetime.ticks /输出数据的值

1000000001 233.23

1000000002 233.34

1000000006 234.23 ......

Taks/Thread#2在给定时间戳处生成以下数据

datetime.ticks /输出数据的值

1000000002 33.32

1000000005 34.34

1000000015 54.32 ......

我不需要在.Net运行时对齐时间戳,我首先保留数据并在稍后处理R或Python中的数据.

我的要求:

  • 快速写入,快速写入,快速写入:可能发生的情况是,我每秒生成100,000到1,000,000个数据点,需要保持(最坏情况)或保留在内存中的数据.可以在自己的线程上运行写入,因此这个过程可能会滞后于数据生成过程,但限制是16gb RAM(64位代码),更多低​​于此.

  • 首选是柱状数据库格式,因为它很适合我以后想要查询数据的方式,但如果它对上面的例子有意义,我可以接受任何其他结构(如果所有其他要求,文档/键值也可以.满足,特别是在写入速度方面).

  • 可以从.Net中引用的API.示例:HDF5可能被一些人认为是有能力的,但我发现他们的.Net端口很糟糕.支持.Net好一点的东西会有好处但是如果满足所有其他要求那么我可以处理类似于HDF5 .Net端口的东西.

  • 如果可能的话,并发写:如前所述,我喜欢从不同的任务/线程同时写入数据.

  • 我受到16GB内存的约束(在64位运行.Net进程),因此我可能会寻找一些不纯粹在内存中的东西,因为我有时会产生更多的数据.内存中有时会持续存在或纯粹的持久性模型可能更可取.

  • 嵌入式的优先级,但如果客户端/服务器解决方案中的服务器可以作为Windows服务运行,那么没有问题.

  • 在数据访问方面,我非常喜欢已经存在R和Python接口的数据库解决方案,因为我喜欢在Python中使用Panda库进行时间序列对齐和其他分析并在R中运行分析.

  • 如果API /库支持SQL/SQL-like/Linq/like查询,那将是非常好的但通常我只需要绝对的简单骨骼,例如在开始和结束日期之间加载柱状数据(给定"key"/ index是这样的格式)因为我在R/Python中分析和运行查询.

  • 如果它带有管理控制台或数据可视化工具,那将是一个加号但不是必须的.

  • 应该是开源的或者在"达到"范围内定价(不,KDB在这方面没有资格;-)

好的,这是我到目前为止所拥有的,而且我得到的全部是因为大多数数据库解决方案在写入性能要求上已经失败了:

  • Infobright和Db4o.我喜欢我到目前为止阅读的内容,但我承认我没有检查任何性能统计数据
  • 我自己完成的事情.我可以轻松地以二进制格式存储值类型并通过datetime.ticks索引数据,我只需要以某种方式编写脚本来加载/反序列化Python/R中的数据.但如果我想添加并发,查询引擎和其他好东西,那将是一项艰巨的任务.因此,我寻找已经存在的东西.

Chi*_*key 13

我不能评论 - 低代表(我是新来的) - 所以你得到一个完整的答案而不是......

首先,您确定需要一个数据库吗?如果快速写入速度和R的可移植性是您最关心的问题,那么您是否考虑过平面文件机制?根据你的意见,你愿意批量写出,但你需要坚持; 如果这些是我的要求我会编写一个快速闪存的直接缓存系统然后构建一个单独的任务,定期获取磁盘文件并将它们移动到R的数据存储中,这只有在R读取平面时文件还不够.

如果您可以事后进行对齐,那么您可以将线程写入主并行循环中的单独文件,每隔一段时间关闭一个文件,并将对齐和数据库加载保留到子进程.

所以(在蹩脚的伪代码中),构建一个你用后台工作者调用的线程进程,并包含一个唯一标识每个worker的线程名字符串,从而标识每个文件流(任务/线程):

file_name = threadname + '0001.csv' // or something
open(file_name for writing)
while(generating_data) {
    generate_data()
    while (buffer_not_full and very_busy) {
        write_data_to_buffer
        generate_data()
    }
    flush_buffer_to_disk(file_name)
    if(file is big enough or enough time has passed or we're not too busy) {
        close(file_name)
        move(file_name to bob's folder)
        increment file_name
        open(file_name for writing)
    }
)
Run Code Online (Sandbox Code Playgroud)

高效,快速的文件I/O和缓冲是一个简单而常见的问题.没有比这更快的了.然后,您可以编写另一个进程来执行数据库加载,而不是在那里表现不佳:

while(file_name in list of files in bob's folder sorted by date for good measure)
{
    read bob's file
    load bob's file to database
    align dates, make pretty
}
Run Code Online (Sandbox Code Playgroud)

我不会在C#中编写那个部分,我会批量编写脚本并使用数据库的本机加载器,它将与您从头开始构建的任何内容一样快.

如果你在同一个硬件上运行,你必须确保这两个循环不会干扰太多.也就是说,以更高的优先级运行任务线程,或者构建一些互斥或性能限制器,以便在线程运行时数据库负载不会占用资源.我肯定会隔离数据库服务器和硬件,以便不损害平面文件的文件I/O.

如果你在Unix上,FIFO队列可以工作,但你不是.:-)

此外,我想,硬件对数据库引擎的性能影响会更大.如果你的预算有限,我猜你是在使用COTS硬件,那么弹出固态驱动器可能会相当便宜地提高性能.正如我所说的那样,将数据库存储与平面文件存储分开会有所帮助,而R,数据库和线程的CPU/RAM应该都是理想的隔离.

我所说的是,DB供应商的选择可能不是你最大的问题,除非你有很多钱可花.否则你将在大多数情况下受到硬件限制.数据库调优是一门艺术,虽然您可以在高端获得较小的性能提升,但拥有一名优秀的数据库管理员将使大多数数据库保持同一性能.我会看看R和Python支持的内容以及您对此感到满意.如果你以柱状方式思考,那么看看R和C#对Cassandra(我的投票),Hana,Lucid,HBase,Infobright,Vertica和其他人的支持,并根据价格和支持选择一个.对于单个商品机器上的传统数据库,我还没有看到MySQL无法处理的任何内容.


Mat*_*olf 2

这不是为了回答我自己的问题,而是为了跟踪我迄今为止测试过的所有数据库以及为什么它们还没有满足我的要求:每次我尝试写入 100 万个单个对象(1 个长型,2 个浮点型)到数据库。对于 ooDB,我将对象放入集合中并编写集合本身,与 Redis 等键/值的情况类似,但也尝试将简单的整数 (100 万) 写入 InfoBright 等列式数据库。

  • Db4o,写入速度非常慢:一个集合中的 100 万个对象大约需要 45 秒。后来我优化了集合结构,也单独写了每个对象,这里不太喜欢。
  • InfoBright:同样的事情,写入速度非常慢,这让我很惊讶,因为它以柱状格式组织数据,但我认为“知识树”仅在查询数据时起作用,而不是在保存平面数据结构/表时起作用-像结构一样。
  • Redis(通过 BookSleeve):适用于 .Net 的出色 API:完整的 Redis 功能(尽管与 Linux 或 Unix 机器相比,在 Windows 机器上运行服务器有一些缺点)。性能非常快...每秒超过 100 万个项目。我使用 Protocol Buffers(protobuf-net,均由 Marc Gravell 编写)序列化了所有对象,仍然需要更多地使用该库,但 R 和 Python 都可以完全访问 Redis DB,这是一个很大的优势。到目前为止很喜欢它。Marc 围绕 Redis 基本功能编写的异步框架非常棒,非常简洁,并且到目前为止一直有效。我还想花更多的时间来尝试 Redis 列表/集合类型,因为到目前为止我只序列化为字节数组。
  • SqLite:我纯粹在内存中运行,并在大约 3 秒内成功写入 100 万个值类型元素。对于纯 RDBMS 来说还不错,显然内存选项确实加快了速度。我只创建了一个连接、一个事务、创建了一个命令、一个参数,并在循环中简单地调整了参数的值,并在每次迭代时运行 ExecuteNonQuery。然后事务提交在循环外运行。
  • HDF5:虽然有一个 .Net 端口,并且也有一个库可以以某种方式处理 R 中的 HDF5 文件,但我强烈建议不要这样做。这纯粹是一场噩梦。.Net 端口写得非常糟糕,哎呀,整个 HDF5 概念非常值得怀疑。它是一个非常古老且在我看来已经过时的存储矢量化/列数据的解决方案。这是 2012 年,而不是 1995 年。如果无法将数据集和向量从之前存储的文件中完全删除,那么我不会称其为烦恼,而是主要的设计缺陷。一般来说,API(不仅仅是 .Net)的设计和编写都非常糟糕,恕我直言,有大量的类对象,没有人在没有花费大量时间研究文件结构的情况下了解如何使用。我认为,现有的文档和示例代码数量非常稀少,这在一定程度上证明了这一点。此外,h5r R 库是一场戏剧,绝对是一场噩梦。它的写得也很糟糕(通常由于错误的刷新,文件在写入时没有正确关闭,并且它损坏了文件),该库甚至在 32 位操作系统上正确安装时也存在问题......而且它一直在继续。我写的有关 HDF5 的文章最多是因为我在这方面花费了大部分时间......并且最终得到了最大的挫败感。拥有一个可从 R 和 .Net 访问的快速列式文件存储系统的想法很诱人,但它并没有兑现其在 API 集成和可用性或缺乏方面所承诺的承诺。

更新:我放弃了对velocityDB的测试,只是因为似乎没有任何适配器可以从R中访问可用的数据库。我目前正在考虑使用图表库编写自己的 GUI,该库可以从写入的二进制文件访问生成的数据,或者通过无代理消息总线 (zeroMQ) 发送数据,或者通过 LockFree++ 发送到“参与者”(我的 gui)。然后我可以从 C# 中调用 R 并将结果返回到我的 GUI。这可能会给我最大的灵活性和自由度,但显然也是最乏味的编码。我在测试过程中遇到了越来越多的限制,随着每次数据库测试,我越来越喜欢这个想法。

结果:感谢您的参与。最后,我将赏金点授予了 Chipmonkey,因为他部分地提出了我认为解决问题的重要要点(尽管我最终选择了自己的不同解决方案)。我最终得到了内存存储中的 Redis 和从 .Net 直接调用 R.dll 之间的混合体。Redis 允许不同的进程访问其存储在内存中的数据。这使得它成为一种方便的解决方案,可以将数据作为键/值快速存储在 Redis 中,然后从 R 中访问相同的数据。此外,我通过其 .dll 和优秀的 R.Net 库直接发送数据并调用 R 中的函数。在我的机器上将 100 万个值类型的集合传递给 R 大约需要 2.3 秒,这已经足够快了,因为我可以方便地传递数据、在 .Net 环境之外调用 R 中的计算函数并返回结果同步或异步。