优雅与性能:何时使用冗余列表进行查询?

Posted

技术标签:

【中文标题】优雅与性能:何时使用冗余列表进行查询?【英文标题】:Elegance and Performance: When to use redundant lists for queries? 【发布时间】:2012-03-27 21:20:31 【问题描述】:

编辑:When should and shouldn't you break away from OOP for speed/performance? 可能与这个问题有关。

如果我的问题不清楚,我很抱歉;我是一个业余爱好者,如果我受过更好的教育,我可能会知道一些更具体的相关术语。请允许我使用一些简单的示例代码。

class EmployeeRecords(object):
    """A record of all employees."""
    def __init__(self):
        super().__init__()
        self.employees = []
        # The following two attributes are redundant.
        self.at_office = "LAN":[], "DET":[], "KAL":[]
        self.in_thirties = []

    def register_employee(self, employee):
        """Register a new employee in the records.

        This entire method is redundant.

        """
        self.employees.append(employee)
        self.at_office[employee.office_code].append(employee)
        if 30 <= employee.age < 40:
            self.in_thirties.append(employee)

class Employee(object):
    """An employee record featuring relevant information for queries."""
    def __init__(self, first_name, last_name, age, office_code):
        super().__init__()
        self.first_name = first_name
        self.last_name = last_name
        self.age = age
        self.office_code = office_code


# Instantiation and what-not goes here.
...

print([x for x in my_records.employees if 30 <= x.age < 40])
# VS
print(my_records.in_thirties)

哪个更合适?后一种方法是否被专家普遍认为是不好的形式?

--更多信息--

在 EmployeeRecords 中注册时,将 Employee 实例添加到相关列表中似乎在计算上可能更有效。但是,我最近一直在研究 SQL(最后),似乎有效使用它的很大一部分是“数据规范化”:从多个表中删除冗余数据,否则这些数据可以通过更深入的查询获得。

我可以看到并同意拥有冗余数据会导致错误;当我的查询可以通过对象(或者,在 SQL 的情况下是表)关联从单个列表中提取时,为什么还要更新所有这些冗余列表呢?在上面的例子中,列表解析总是会返回正确的信息,但是如果我愚蠢地附加了my_records.employees而不是使用my_records.register_employee,使用my_records.in_thirties会产生意想不到的结果。

这只是一个示例,在代码管理和性能方面,这两种方法几乎没有区别。但在实践中,查询可能涉及在对象列表中搜索列表,这些对象的属性是需要查询其他对象的列表。

为此目的避免冗余列表是否被认为是一种好习惯,还是大多数人认为重复进行非常深入的搜索是否有利?我知道 Python 不是 SQL,但我认为 OOP 非常关注通过使用属性来建立对象之间的关系,因此我可以看到这些类型的列表如何被认为是错误的形式并且容易出现错误。

感谢您的帮助。我没有受过正规教育,虽然我有多年的宠物项目编程经验,但我总是以有效架构的方式学习新事物。这是我多年浏览后关于 SO 的第一篇文章,所以如果这是一个愚蠢或不恰当的问题,请保持温和。我不知道还能去哪里!

-大卫·埃尔南德斯

【问题讨论】:

这确实是一个编程设计问题,而不是 Python 问题。这种简单的缓存可以用任何语言完成。 【参考方案1】:

基本上,这取决于您需要特定事物的频率与您需要它所基于的事物的频率。

如果您曾经对员工进行的唯一查询是那些 30 多岁的人,并且您在进行该查询时遇到了性能问题,那么这是有道理的提前计算。

另一方面,如果这只是您进行的众多查询中的一个,那么将您的数据模型与大量预先计算的东西混在一起就没有多大意义了;保持模型简单并在需要时计算+缓存您需要的内容将使您的代码更易于使用。

只优化你需要的性能,如果这样做会以可维护性/编码时间为代价。(请参阅http://c2.com/cgi/wiki?PrematureOptimization。)

【讨论】:

这是我需要听到的,并且,在发布之后,我从我在编辑中发布的 SO 问题中得到了一些启发。我听说过所有关于过早优化的陷阱,但我从来没有编写过足够大的程序,以至于它成为一个很大的问题。在这种情况下,你是对的;我将继续进行深度查询,直到明确我~需要~使用冗余列表。非常感谢!

以上是关于优雅与性能:何时使用冗余列表进行查询?的主要内容,如果未能解决你的问题,请参考以下文章

何时在 DbContext 上执行查询

SQL 连接与单表:性能差异?

mongodb性能优化

何时使用查询参数与矩阵参数?

何时在 oracle 查询中使用提示 [重复]

给定连接上的慢 MySQL 查询何时会影响其他连接?