RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 632575
Accepted
while1pass
while1pass
Asked:2020-02-26 05:41:36 +0000 UTC2020-02-26 05:41:36 +0000 UTC 2020-02-26 05:41:36 +0000 UTC

如何加快从数据库读取数据或减少请求次数?

  • 772

Django/REST-Framework/PostgreSQL 项目。

有主要是一对多连接的模型,以及对数据库进行查询的 API。

现在加载一些页面时大约有 700-1500 个查询到数据库,数据库正在增长并且会进一步恶化。看哪条路解决问题?

编辑现有代码/使用原始查询?据我了解,这是一个临时解决方案,我们将再次触及天花板。

键值存储 - Redis/memcached 等?但是在这里,正如我也假设的那样,数据增长存在上限,我们必须改变项目的结构。

在寻找解决方案时,我看到了另一种方法——阻止从数据库中读取。解释一下。我们可以在构建 API 时使用它吗?比如逐渐给数据,最多一条记录,传给消费者?我们可以结合使用块读取和键值存储吗?

关于这些方法还有哪些其他评论以及我没有考虑到的内容?


添加了部分代码以供理解。有两个相关模型。第一个对应表中的 120 条记录,第二个 - 超过 10000(每个元素大约 100 个 Property 对象)

class Element(models.Model):
    name = models.CharField(verbose_name="Name", max_length=255, blank=True, null=True)

    class Meta:
        verbose_name = "Element"
        verbose_name_plural = "Elements"


class Property(models.Model):
    element = ForeignKey(Element, related_name='properties')
    title = models.CharField(max_length=255)
    type = models.CharField(max_length=50, choices=TYPE)
    value = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        verbose_name = "Property"
        verbose_name_plural = "Properties"
        ordering = ('title',)

从 API 中,我得到以下结构——我需要从表格的某些行中进行选择property

[
    {
        "name": "Lithium",
        "properties": {
            "group": "1",
            "atomic_number": "3",
            "symbol": "Li",
            "period": "2",
            "atomic_weight": "6.941",
            "type": "alkali"
        }
    },
    {
        "name": "Beryllium",
        "properties": {
            "group": "2",
            "atomic_number": "4",
            "symbol": "Be",
            "period": "2",
            "atomic_weight": "9.012182",
            "type": "alkaline"
        }
    }


   ...

在我使用视图请求的方法之一中(obj 是一个 Element 模型对象)

def get_properties(self, obj):
        properties = ['Symbol', 'Group', 'Period', 'Type', 'Atomic weight', 'Atomic number']
        func = lambda property: obj.properties.get(title=property).value if obj.properties.filter(title=property).exists() else None
        data = map(func, properties)

        return dict(zip(properties, data))

这里这个函数中的检查使对数据库的请求数增加了一倍,我们删除了检查 - 请求数下降了一半,我不明白如何绕过

 func = lambda property: obj.properties.get(title=property).value if obj.properties.filter(title=property).exists() else None
база-данных
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Никита Конин
    2020-03-07T00:08:56Z2020-03-07T00:08:56Z

    在我看来,这里的问题更有可能是不正确的查询构造和架构,而不是数据库性能的严重问题。

    每页 700-1500 个请求是禁止的。我确信请求的数量可以大大减少。

    例如,如果我们以您引用的方法为例:

    def get_properties(self, obj):
        properties = ['Symbol', 'Group', 'Period', 'Type', 'Atomic weight', 'Atomic number']
        func = lambda property: obj.properties.get(title=property).value if obj.properties.filter(title=property).exists() else None
        data = map(func, properties)
    
        return dict(zip(properties, data))
    

    在 10 分钟内,我设法重写了它,使其仅使用一次对数据库的调用:

    def get_properties(self, obj):
        titles = ['Symbol', 'Group', 'Period', 'Type', 'Atomic weight', 'Atomic number']
        props = {p.title: p.value for p in obj.properties.filter(title__in=properties).values('title', 'value')}
        data = {title: None for title in titles}
        data.update(props)
        return data
    

    我确信您的代码中这样的地方并不少,只需重写它们就可以显着提高性能,这样它们就不会生成不必要的请求,也不会重新计算已经计算过的内容,等等。

    • 1
  2. Eugene Bartosh
    2020-02-26T08:12:06Z2020-02-26T08:12:06Z

    在现代云系​​统和良好的旧大型机系统中,对来自用户程序的请求数量有限制。如果用户的程序超出了限制,它会被踢出而不说话。典型限制为 150 个 SQL 查询 + 100 个 DML 查询。触发器中的请求数量也有限制,但这是一个单独的问题。

    加载页面时,请求的数量不能超过某个合理的数量,通常<10。如果你有 1500 - 它根本不属于任何标准,是时候向那些如此勤奋地生成这些请求的开发人员提出问题了:-)

    好吧,你自己判断——毕竟,你可以通过一个请求选择所有 20 到 30 岁的人,或者你可以用一个单独的请求来追逐他们中的每个人……如果可以一次全部分开,为什么要分开呢?

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5