SQLite的可扩展性如何?

188

最近我读到了一个关于 SQLite vs MySQL 的问题,并且答案指出 SQLite 不适合大规模应用,官方网站也有所确认

那么 SQLite 到底有多强的可扩展性?它的上限是什么?

9个回答

440
昨天我发布了一个小型网站*,用于跟踪你的声誉(reputation),它使用了一个共享的SQLite数据库供所有访问者使用。不幸的是,即使对我的主机负载很小,它运行得非常慢。这是因为每次有人查看页面时整个数据库都会被锁定,因为它包含更新/插入。然后我很快切换到了MySQL,虽然我没有太多时间测试它,但它似乎比SQLite更具可扩展性。我只记得页面加载缓慢,有时在尝试从sqlite中执行查询时会出现数据库锁定错误。话虽如此,我仍在从SQLite运行另一个网站。不同之处在于该站点是静态的(即只有我可以更改数据库),因此它适用于并发读取。故事的寓意:只在数据库更新很少的网站上(每个页面加载时间间隔大于)使用SQLite。

编辑: 我刚意识到我可能没有公平地评价SQLite——当我从网页中服务SQLite数据库时,我没有为任何列建立索引。这部分导致我经历了减速。然而,关于数据库锁定的观察是正确的——如果你有特别繁重的更新,SQLite的性能无法与MySQL或Postgres相媲美。

另一个编辑:自从我在差不多3个月前发布了这篇文章以来,我有机会仔细研究了SQLite的可扩展性,并且用了一些技巧后,它的可扩展性还是不错的。正如我在第一个编辑中提到的,数据库索引可以极大地减少查询时间,但这更像是关于数据库的一般性观察,而非关于SQLite的。然而,还有一个技巧可以加速SQLite:事务。每当你需要进行多个数据库写操作时,请将它们放在事务内。不像每次发出写查询时都会写入(并锁定)文件,当事务完成时,写入只会发生一次。

我在第一个段落中提到的网站已经切换回SQLite,一旦我在几个地方调整了我的代码,它运行得非常顺畅。

*该网站不再提供


3
MySQL的“经典”数据库引擎MyISAM在并发读写操作方面与SQLite存在相同的问题。实际上,它在写操作中锁定它触及的每一行,使得无法扩展写入密集型应用程序。尽管如此,它仍然可以很好地为许多Web应用程序提供服务。 - Henning
3
@porneL说得没错,但是没有使用索引的SQLite比没有使用索引的MySQL慢了一个数量级,而且我在第二次编辑中也提到了事务。我仍然认为回答的进展有一定意义——它展示了我最初对SQLite的天真使用以及相对较差的性能。我预计那些刚接触该平台的人会遇到类似的问题,希望他们可以理解第一段,然后阅读后续的编辑内容,意识到有方法可以加速SQLite并获得可接受的性能。 - Kyle Cronin
1
你能告诉我们你的网站每秒大约有多少次点击吗? - NoobOverflow
4
新版的SQLite也提供了预写式日志(WAL),这可能会减轻读写循环带来的痛苦。事物是会变化的。 - Lasse V. Karlsen
1
例如,每当可能时,我都会尽量确保我的模式更新与生产代码向后兼容。然后我会在生产环境中更新模式,然后推送依赖于新模式的代码更改。@KonstantinTarkus - Kyle Cronin
显示剩余11条评论

64

Sqlite在单用户方面是可扩展的,我有一个多GB的数据库表现非常出色,我没有遇到太多问题。

但是它确实只能支持单用户,所以这取决于你所谈论的扩展类型。

回应评论。请注意,没有任何东西阻止在多用户环境中使用Sqlite数据库,但是每个事务(实际上是修改数据库的每个SQL语句)都会对文件进行锁定,这将完全阻止其他用户访问数据库。

因此,如果对数据库进行了大量修改,则基本上会很快遇到扩展问题。另一方面,如果读访问相对于写访问更多,情况可能不那么糟糕。

但是Sqlite当然可以在多用户环境中运行,但是性能不佳。


6
SQLite 3 支持在其他用户写入时进行读取。 - Alix Axel
3
请注意,以上评论已经过时。随着新的WAL系统,写入和读取可以同时进行,从而提高可扩展性。 - Lasse V. Karlsen
能否在任何关系型数据库(如SQL Server或Oracle等)中创建即时导出记录到SQLite的功能? - ILoveStackoverflow

33

SQLite驱动着sqlite.org网站以及其他访问量很大的网站。他们建议如果每天的点击量少于100k,那么SQLite应该可以正常工作。而且这是在他们推出“预写日志”功能之前写的。

如果你想加速SQLite的速度,请按照以下步骤操作:

  • 升级到SQLite 3.7.x版本
  • 启用预写日志
  • 运行以下pragma语句:"PRAGMA cache_size = Number-of-pages;" 默认大小(Number-of-pages)是2000页,但如果你提高这个数字,那么将会提高直接从内存中运行的数据量。

你可能想看一下我在YouTube上的视频,名为"通过预写日志改善SQLite性能",它展示了如何使用预写日志并演示了写入速度提高5倍的效果。


26

Sqlite是一种桌面端内嵌式数据库。而SQL Server、MySQL、Oracle等则是服务器端数据库。

桌面端数据库天生不适合用于支持对数据存储的并发写入访问,这意味着大部分网站都不适合使用它作为数据存储方式。如果您需要进行任何登录操作,那么您可能需要对数据库进行写入访问。


7
我不同意“这几乎包括所有曾经创建的网站”的说法。如果网站有高负载,你是正确的。例如,Trac默认使用SQLite,在小团队中表现非常好。 - Andrew Burns
2
给它一些时间:你会有两个开发者同时访问同一个字段,然后它就会崩溃。 - Joel Coehoorn
3
你认为什么是“噎住”?从你的回答中我猜测你对SQLite没有太多经验。SQLite会在操作时锁定整个文件,因此可能会有延迟,但在你提出的情况下几乎不可能发生“噎住”的情况。 - Andrew Burns
3
安德鲁,虽然SQL Lite适用于小团队,但并不意味着它具有可扩展性。要实现可扩展性,需要满足良好的扩展要求,即能够在大型团队中表现出色。据我所知,SQL Lite无法扩展到超过相当低门槛的大型团队/并发数据库操作。 - Pop Catalin
5
@Justice。这个回答没有支持SQLite可扩展性的证据。没有人的回答更好一些。 - GateKiller
显示剩余2条评论

23
你读过这篇 SQLite 文档吗 - http://www.sqlite.org/whentouse.html

SQLite通常作为低到中等流量的网站(也就是说,99.9%的所有网站)的数据库引擎而运作良好。 SQLite可以处理的网络流量取决于网站如何重度使用其数据库。一般来说,每天获取少于100K次点击量的任何网站都应该能够很好地使用SQLite。这个100K次点击量的数字是一个保守估计,而不是一个硬性的上限。SQLite已经被证明可以处理比那多10倍的流量。


3
我非常同意这个观点。如果需要的话,99% 的网站可以使用 SQLLite 来处理。但是,另一方面,99% 的网络流量都流向排名前 1% 的最大型网站。 - djangofan
7
“每日100,000次点击”这个度量标准完全是无用的。 “点击”通常定义为HTTP GET请求,一个包含许多切片图片的网站可能会在每个页面视图上获得40多个“点击”——这些都不会触及数据库。即使文档中犯了点击==页面视图的错误,它仍然具有误导性。SQLite在写入时锁定整个数据库。虽然它可以勇敢地为浏览记录的100,000个页面视图提供服务,但在写入密集型应用程序(电子商务、留言板等)中它将崩溃。 - jamieb

10

SQLite的可扩展性高度取决于所使用的数据及其格式。对于超长表(如GPS记录,每秒钟一条记录),我有一些艰难的经历。经验表明,由于索引持有不断增长的二叉树的平衡,并且有时间戳的索引会经常需要重新平衡,因此SQLite会分阶段地变慢(而且你知道那棵树很重要,但搜索过程却很缓慢)。因此,在大约1GB(非常粗略,我知道)时,查询在我的情况下变得迟缓。结果因人而异。

需要记住的一件事是,尽管所有吹嘘,SQLite并不适用于数据仓库。 SQLite有各种不推荐的用途。SQLite背后的优秀人员自己说:

看待SQLite的另一种方法是:SQLite不是为了取代Oracle而设计的。它是为了取代fopen()而设计的。

这导致了主要争论的问题(非量化的,抱歉,但是定性的),SQLite不适用于所有用途,而MySQL可以涵盖许多不同的用途,即使不是理想的。例如,你可以让MySQL存储Firefox的cookie(而不是SQLite),但必须将该服务始终保持运行状态。另一方面,你可以在SQLite上运行事务性网站(像许多人所做的那样),而不是MySQL,但会有很多停机时间。


1
你可以通过分片数据来解决拥有非常大的索引表的问题,例如每天/每周一个表。SQLite甚至允许您将表拆分为不同的数据库文件,然后使用“ATTACH DATABASE”创建一个虚拟数据库连接,其中包含所有表(但最多只能限制到62个数据库)。 - Alix Axel

3

我认为一个(数字为1)的Web服务器为数百个客户端提供服务,后端只有一个与数据库的连接,是吗?

因此,在数据库中没有并发访问,因此我们可以说数据库正在以“单用户模式”工作。在这种情况下,讨论多用户访问是没有意义的,因此SQLite与任何其他基于服务器的数据库一样有效。


1
谢谢GateKiller,但请具体说明“低流量网站”。 - Ice

3
这样想吧。每次有人使用SQL Lite时,它都会被锁定(SQLite在读取时不会锁定)。因此,如果您提供的是具有多个并发用户的网页或应用程序,则只能有一个人同时使用SQLLite。所以这里就存在着一个扩展问题。如果它是一个单人应用程序,比如音乐库,其中包含数百个标题、评级、信息、使用情况、播放和播放时间,那么SQL Lite将可以很好地扩展,可以容纳数千甚至数百万条记录(硬盘容量允许)。
另一方面,MySQL适用于服务器应用程序,在这些应用程序中,人们遍布全球会同时使用它。它不会锁定,并且相当大。因此,对于您的音乐库,MySql可能过于臃肿,因为只有一个人会看到它,除非这是一个共享的音乐库,数千人添加或更新它。然后MYSQL将是要使用的。
因此,从理论上讲,MySQL比Sqllite更适合扩展,因为它可以处理多个用户,但对于单个用户应用程序来说则过于庞大。

6
SQLite 在读取时不会锁定,将 s/uses it/writes to it 翻译为“将其写入”。 - Gregg Lind
6
你的回答很容易被误解。SQLite仅在写请求时进行锁定。我们正在使用SQLite处理超过50GB的医疗数据,并为数百个同时浏览和查询的Web客户端提供服务。它的读取性能从未比最近的MySQL差。 - Berk D. Demir
3
MySQL 的 MyISAM 在并发访问方面并不比 SQLite 更好。MySQL 经常使用表级锁,并且除非使用 MyISAM 布局最优的少数情况下,否则不能进行并发写入。除非选择 InnoDB(它有自己的问题,比如数据文件永远不会缩小),否则选择 MySQL 也许不会更好。 - Kornel

1
SQLite的网站(您所引用的部分)表明它可以用于各种多用户情况。
我认为它可以处理相当多的数据。在我的经验中,它一直非常快速。当然,您需要对表进行索引,并在编写代码时确保使用参数化查询等技术来提高性能。基本上,这与您使用任何数据库时要做的事情是相同的。

使用事务非常关键,特别是对于SQLite数据库。 - Kornel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接