在这个简单的基准测试中,为什么SQLite比Redis更快?

tor*_*eff 25 python sql sqlite redis

我在我的本地机器上做了简单的性能测试,这是python脚本:

import redis
import sqlite3
import time

data = {}
N = 100000

for i in xrange(N):
    key = "key-"+str(i)
    value = "value-"+str(i)
    data[key] = value

r = redis.Redis("localhost", db=1)
s = sqlite3.connect("testDB")
cs = s.cursor()

try:
    cs.execute("CREATE TABLE testTable(key VARCHAR(256), value TEXT)")
except Exception as excp:
    print str(excp)
    cs.execute("DROP TABLE testTable")
    cs.execute("CREATE TABLE testTable(key VARCHAR(256), value TEXT)")

print "[---Testing SQLITE---]"
sts = time.time()
for key in data:
    cs.execute("INSERT INTO testTable VALUES(?,?)", (key, data[key]))
    #s.commit()
s.commit()
ste = time.time()
print "[Total time of sql: %s]"%str(ste-sts)

print "[---Testing REDIS---]"
rts = time.time()
r.flushdb()# for empty db
for key in data:
    r.set(key, data[key])
rte = time.time()
print "[Total time of redis: %s]"%str(rte-rts)
Run Code Online (Sandbox Code Playgroud)

我希望redis执行得更快,但结果表明它更慢:

[---Testing SQLITE---]
[Total time of sql: 0.615846157074]
[---Testing REDIS---]
[Total time of redis: 10.9668009281]
Run Code Online (Sandbox Code Playgroud)

所以,redis是基于内存的,sqlite怎么样?为什么redis这么慢?当我需要使用redis并且需要使用sqlite时?

Har*_*hof 39

来自redis文档

Redis是一个服务器:所有命令都涉及网络或IPC往返.将它与嵌入式数据存储(例如SQLite,Berkeley DB,Tokyo/Kyoto Cabinet等)进行比较是没有意义的......因为大多数操作的成本完全由网络/协议管理决定.

虽然在某些情况下确认速度问题,但这确实有意义.例如,在多个并行访问的情况下,Redis可能比sqlite执行得更好.

适合正确工作的正确工具,有时它会在其他时候重新发布,而其他时候则完全不同.如果这个速度测试能够正确显示你的应用程序将会切实做什么,那么sqlite会更好地为你服务,你做这个基准测试是件好事.

  • 我是这句话的原作者,我不同意你的不同意见;-)基准测试是比较苹果和苹果,所以你需要了解苹果是什么来评估它的表现. (9认同)
  • +1,虽然我当然不同意这句话:我一般不感兴趣*如何*有效的东西(好吧,但不是基准测试时),但对于手头的工作有多快 - 如果有一件事是由于一些架构决策明显变慢,但仍然没有使比较"毫无意义" (3认同)

小智 28

目前的答案提供了有关Redis为何失去这个特定基准的洞察力,即针对服务器执行的每个命令产生的网络开销,但是没有尝试重构基准代码以加速Redis性能.

代码的问题在于:

for key in data:
    r.set(key, data[key])
Run Code Online (Sandbox Code Playgroud)

您需要100,000次往返Redis服务器,这会带来很大的I/O开销.

这是完全没必要的,因为Redis为某些命令提供了"批处理"功能,所以对于SET有MSET,所以你可以将上面的内容重构为:

r.mset(data)
Run Code Online (Sandbox Code Playgroud)

从100,000次服务器跳转到1.您只需将Python字典作为单个参数传递,Redis将在服务器上自动应用更新.

这将使您的特定基准测试产生重大影响,您应该看到Redis的性能至少与SQLite相当.

  • 好点子.但是如果使用`r.mset`将`r.set`的循环替换为单个批量操作,那么在sqlite端你还需要将多个`INSERT`语句的循环替换为单个批量`INSERT` .IMO,只有这样才能成为真正可靠的基准,比较两端的批量与批量操作. (10认同)
  • 这是一个真正的比较. (2认同)

Rei*_*ica 11

SQLite非常快,你只需要一个IO动作(在commit)上.由于它通过网络,Redis正在做更多的IO.更多的苹果与苹果的比较将涉及通过网络(如MySQL或PostgreSQL)访问的关系数据库.

你也应该记住,SQLite的已经存在了很长一段时间,并且非常高度优化.它受到ACID合规性的限制,但实际上您可以将其关闭(如某些NoSQL解决方案所做的那样),并使其更快.

  • @swasheck是的,它并不像连接到另一台机器那么糟糕,但它仍然涉及系统调用和更复杂的通信(与直接使用自己的进程内存相比). (3认同)

小智 8

刚注意到你没有管道redis的提交.使用piplines减少时间:

[---测试SQLITE ---]

[sql的总时间:0.669369935989]

[---测试REDIS ---]

[redis总时间:2.39369487762]