我即将开发一个主要存储用户加密数据的应用程序。借助 AES 密钥对每条数据进行加密,该密钥本身使用每个授权用户的公共 RSA 密钥进行加密。
鉴于非加密数据的数量可以忽略不计(可能只有用户登录、一些日期和外键),我想知道诸如 PostgreSQL 或 MySQL 之类的“标准 DBMS”是否是一个不错的选择。
实际上,这些 DBMS 已针对处理不同类型的数据(文本、整数、日期等)、索引、过程演算、聚合等进行了优化。
就我而言,我将存储的绝大多数数据将是大块文本(或者可能是二进制数据)。大部分所需的演算将在解密后在客户端进行处理。
因此,我也无法解析我的数据。所以即使我有一个巨大的数据库,它也不能被称为“大数据”。但是,我想知道 MongoDb、MemSQL 或其他什么不是更准确的选择。如果不是,那么最好的 DBMS 以及将其用于我的目的的最佳方式是什么?
换句话说,我认为每个 DBMS 都必须做出牺牲才能在最重要的特性上更高效。我也认为上面详述的案例并不是那么随意。所以我假设有很多我不需要的功能(或者我不能使用,例如 FULLTEXT 搜索)。另一方面,我可能需要“标准 DBMS”丢弃的功能。
经验法则:如果您的数据结构良好、众所周知(预先)并且每个条目的大小有限(没有大型 BLOB),那么关系数据库非常擅长存储它。即使您不使用高级索引功能。
管理空间,尤其是数据文件中的空白空间,是一个非常难以解决的问题。关系数据库已经处理这个问题超过 20 年了——为此值得使用它们。除此之外,关系数据库还让您受益于长期的性能调优。它们运行高度优化的本机代码,因此您不必为糟糕的 Java 实现、糟糕的网络堆栈、过度使用 memcpy、垃圾收集、粗锁以及新产品(尤其是 noSQL 的东西)往往具有的所有其他问题而苦苦挣扎。
要存储加密数据,请使用 BINARY 数据类型。MSSQL、MySQL 和 Postgres 都支持这些类型。您可能不想直接对这些类型进行操作(尽管您可以根据需要进行二进制操作)。另请注意,在数据库本身中实现加密/解密相对容易,因为上述所有支持加密库。您还将受益于键/外来列的索引,因此您可以快速找到您的数据。关系数据库是小型值类型的出色键/值存储 - 即使在小盒子上,SQL Server 也可以轻松获得超过 1-10M 的键/值查找/秒 - 我希望 MySQL 和 PostGres 会在同一个球场上提供结果。
也很容易找到能够高效查询关系数据库的程序员。SQL 已经存在了很长时间,它是一种非常强大的语言。MSSQL 甚至会给你自动并行执行。一些程序员不会“理解”它——但如果他们不理解,他们很可能也不会理解并行性或 lambda 表达式(现代程序员的两项关键技能)。
除了所有这些优点之外,您还可以获得适用于所有标准关系数据库的强大备份和监控工具。
所以基本上,除非你有一个非常好的理由使用 NoSQL——只使用关系数据库。
问题中没有足够的信息来做出明智的决定,但这里有一些基本要点。如果您想了解更多详细信息,请详细说明数据将如何被查询,预计会增长多大,加密段应该有多大等等。
所以,一般来说——不管其他什么决定,我都会将“控制数据”(用户登录、一些日期等)放入您选择的 RDBMS 中。就其余数据而言,有一些考虑:
如何检索加密信息?你要搜索二进制字符串吗?有一些元数据可以帮助找到正确的值吗?键值对?
如果通过键查找进行访问,那么带有某种本地缓存(如 memcache)的 Berkley DB 或 Mongo 将绰绰有余。
如果成功的查找需要更多的“思考”,则可能需要关系存储来支持查找逻辑。
不建议使用指向文件的 DBMS(如 Mongo 所做的那样)来存储文本,至少不适合您的长度的文本。每次您想要访问单个字符串时,都意味着 I/O,我们都知道这对性能有什么影响。所以确实,你应该坚持使用 MySQL 甚至 SQL Server(如果有能力的话)。
主要是因为它们每个都有专门针对这种数据的数据类型:TEXT。我多次听说 TEXT 适合只存储文本,作为 VARCHAR 甚至 VARCHAR(MAX) 的替代品。这是错误的。数据库引擎对 TEXT 数据类型的处理方式不同,当然也针对您的情况进行了优化。
此外,如果您的表中的行没有被完全访问,即。其他列经常被查询,但您的 TEXT 列(不是“SELECT *”类型的查询),您应该考虑在1NF中转换表,并仅在需要时引用巨大的 TEXT 列。
但是,如果您决定将所有数据保存在一个表中,则必须使用索引。你想要的最后一件事是全扫描,它会立即填满你的缓冲区缓存。