【问题标题】:Why is Postgres query faster than Redis query?为什么 Postgres 查询比 Redis 查询快?
【发布时间】:2018-08-19 17:16:45
【问题描述】:

我正在学习 Redis,以及自从它是内存数据库以来它的速度如何。在我的 Django 应用程序中,我有一个包含大约 1500 行的 Postgres 表。该模型只有两个字段“名称”和“发生”。为了测试查询内存不足的对象比从我相信存储在磁盘上的本地数据库中查询的速度快多少,我创建了两个查询

1) 使用 Django 对象管理器通过查询进行简单排序

2) Redis 服务器上的 ZRANGE 命令,从 Redis 排序集。

在进行这两个查询之后,我发现从 Redis 排序集中获取相同数量的项目所花费的时间是进行 Postgres 查询所花费的 250 倍。这是为什么呢?

脚本

import json
import redis
import datetime

from django.http import HttpResponse
from django.shortcuts import render

from wikipedia.models import Word

redis_server = redis.Redis("localhost")

def get_word_results(request):
    now = datetime.datetime.now()
    words = Word.objects.all().order_by('-occurrence')
    after = datetime.datetime.now()

    diff = (after - now).total_seconds() * 1000
    print(diff)

    rnow = datetime.datetime.now()
    words_redis = redis_server.zrange(name='myzset', start=0, end=-1, withscores=True)
    rafter = datetime.datetime.now()

    diff2 = (rafter - rnow).total_seconds() * 1000
    print(diff2)

结果

0.199
48.048

【问题讨论】:

    标签: django postgresql time redis


    【解决方案1】:

    请记住,redis 不是通用数据库。有一些查询或使用老式的 rdbms 是要走的路,有些则 redis 超越了 rdbms。 Redis 为您提供对键值存储数据的闪电般快速的读取和写入。即,“对于给定的单词,我想检索出现次数”,而不是“我希望所有单词都按出现次数排序。”

    所以,例如:

    def prep_redis():
        for word in Word.objects.all():
            redis_server.set(word.name, word.occurrence)
    
    def test_lookup_postgres(name):
        # start = datetime.datetime.now()
        p = Word.objects.get(name=name)
        # end = datetime.datetime.now()
        # diff = end - start
        # print('postgres took %s ms' % (diff * 1000,))
        return p.occurrence
    
    def test_lookup_redis(name):
        # start = datetime.datetime.now()
        value = redis_server.get(name)
        # end = datetime.datetime.now()
        # diff = end - start
        # print('redis took %s ms' % (diff * 1000,))
        return value
    
    def main():
        from timeit import Timer
        prep_redis()
        r_timer = Timer(lambda: test_lookup_redis('sesame'))
        p_timer = Timer(lambda: test_lookup_postgres('sesame'))
        print('For 1000 runs, redis: %s' % (r_timer.timeit(number=1000),))
        print('For 1000 runs, postgres: %s' % (p_timer.timeit(number=1000),))
    

    在这里,我们预计 redis 比 postgres 更快。

    相比之下,redis 在处理较大的数据结构时非常慢,因为序列化和反序列化数据所需的时间超过了 I/O 成本:

    RAM 的速度和内存带宽对于全局性能似乎不太重要,尤其是对于小型对象。但是对于大对象(>10 KB),它可能会变得很明显。通常,购买昂贵的快速内存模块来优化 Redis 并不是很划算。 Redis benchmarks

    【讨论】:

    • 谢谢 2ps,这真的很有帮助!
    【解决方案2】:

    您的测试正在构建数据库查询,但实际上并未执行它。将您的行更改为:

    words = list(Word.objects.order_by('-occurrence'))
    

    这将强制对查询进行评估。 (有关详细信息,请参阅文档的this section。)

    【讨论】:

    • 谢谢凯文!您的两个回答对我更多地理解这个问题都非常有帮助。如果我可以将两者都标记为答案,我会:)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    相关资源
    最近更新 更多