背景
在当前的项目中,我正在使用MySQL和SQLite相结合。我目前为每个用户提供自己的SQLite数据库,以规避我的提供商1GB MySQL数据库的限制。这种方法效果还不错,性能也很好,但是我知道未来对这些平面文件数据库进行持续维护将是一场噩梦。
SQLite令人惊讶地强大,并支持一些相当复杂的SQL查询。然而,我正在考虑使用MongoDB来使用一些NoSQL技术处理用户的大量数据。每个用户可能会生成超过60,000行数据。随着用户数量不断增加,我需要担心未来的性能问题。
-
复杂性
我对MongoDB和其他NoSQL数据库的担忧是它们似乎更受限于支持什么类型的查询操作。如果您只需要简单的批量查询,那就没什么大问题了,但是我需要执行一些更复杂的联接和过滤操作(联合、区分大小写、分组、偶尔联接等)。
我的示例查询尝试选择艺术家的曲目列表。主要问题是这些艺术家名称可能不匹配。例如,有些人标记为“A Day to Remember”,而有些人标记为“A Day To Remember”。对于区分大小写的查询,这会导致返回多个“不同”的记录,但实际上它们是相同的。通常我通过修剪和LOWER()函数将字段正确地组合在一起。
-
性能
我在本地机器上创建了两个全新的数据库。一个用于MongoDB,一个用于MySQL。由于最终结果必须使用PHP进行交互,因此我正在使用PHP与它们交互。每个数据库目前只有大约9,000条记录,因此在这一点上并不是特别大。
我在我的机器上运行了一些测试,并得出了令人失望的MongoDB结果。让我们考虑以下三个查询...
#1 - MongoDB:约14毫秒,结果不正确
$query = array('artist' => 'A Day to Remember');
$cursor = $collection->find($query);
foreach ($cursor as $row) {
echo $row['artist'] . ' - ' . $row['album'] . ' - #'. $row['track'] . ' ' . $row['title'] . "\r\n";
}
#2 - MongoDB: ~170毫秒,正确的结果
$query = array('$where' => "this.artist.toLowerCase() == 'a day to remember'");
$cursor = $collection->find($query);
foreach ($cursor as $row) {
echo $row['artist'] . ' - ' . $row['album'] . ' - #'. $row['track'] . ' ' . $row['title'] . "\r\n";
}
#3 - MySQL: ~18毫秒,正确结果
$sql = "select artist, album, track, title from radio_files where lower(artist) = 'a day to remember'";
$stmt = $mysqldb->prepare($sql);
$stmt->execute();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo $row['artist'] . ' - ' . $row['album'] . ' - #'. $row['track'] . ' ' . $row['title'] . "\r\n";
}
讨论
也许我没有正确地查询#2,但是看看JavaScript查询引擎的效果。总的来说,这里的记录数量甚至不是很多:数据库中仅有不到9,000条。
我的主要问题是:最终哪种方式更可靠、性能更好,同时满足我的需求?随着我的项目用户群的增长,我计划离开我的受限服务器并获得一些专用设备。通过自己的MySQL安装,我应该能够维护自己的大型MyISAM表格,其中包含很少的关系数据和适当的索引。
但是,如果数据库中有数百万条记录,MySQL的性能会怎样呢?鼓励大家思考、评论和进行一般性讨论。谢谢!