使用OOP时优化多个查询的最佳方法


Best way to optimize multiple queries when using OOP

在使用OOP时,通常如何在遵循DRY原则的情况下优化如下类以提高数据库性能?

class AccountExampleClass
{
    private $_mysqli;
    // Current account ID
    private $_accountId;
    public function loginActions()
    {
        // Stuff to do on login
        // ...
        // Store the current time in last_activity and last_login, using 
        // two queries instead of one.
        $this->updateLastActivity();
        $this->_updateLastLogin();
    }
    // Run on every pageview
    public function updateLastActivity()
    {
        $this->_mysqli->query("UPDATE `accounts` SET `last_activity` = NOW()
            WHERE `id` = $this->_accountId LIMIT 1");
    }
    // Only run on login
    private function _updateLastLogin()
    {
        $this->_mysqli->query("UPDATE `accounts` SET `last_login` = NOW()
            WHERE `id` = $this->_accountId LIMIT 1");
    }
}

这只是一个快速的模型来说明这个问题。last_activity和last_login字段都有一个更新数据库的方法,但有时需要同时更新这两个字段(如loginActions方法所示)。通过使用多个查询,大量资源被浪费,并且延迟增加。

我现在能想到很多方法来做这件事。有些很糟糕,有些很有用。

下面是一个列表:

  • 手动创建一个专门的查询,不要使用方法。
    • +不浪费资源
    • -降低可维护性。
  • 创建一个类似代理的类,可以在执行一组查询之前被告知优化它们。
    • +创建优化查询如果被告知。
    • +可以在类中使用方法
    • -必须指定应该优化的传入查询,并告诉它之后执行查询。
    • -一个小的性能影响。
    • -增加复杂性,因为涉及更多的外部组件。
  • 使用对象来表示一行的当前状态并一次性保存。
    • +简单。
    • -大量不必要的数据被发送到数据库
    • 浪费资源。
    • -如果数据在获取行后发生变化,则会变得更糟。
  • 使用对象来表示一行的状态,但只保存更改的列。
在这种情况下,性能、复杂性和可维护性之间的最佳平衡是什么?

我认为这里的答案是使用ORM层,它将为您处理这个问题,允许您更新对象属性,然后在完成后保存这些更改

在实体上调用持久化方法不会导致立即在数据库上发出SQL INSERT。原则适用于策略称为"事务性后写",这意味着它会延迟大多数SQL命令,直到EntityManager#flush()被调用然后发出所有必要的SQL语句来同步对象用最高效的方式和单一的数据库,短事务,负责维护引用完整性。

http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html

不要预先优化,尤其是以增加复杂性为代价。我认为你增加一堆开销的想法是错误的。

如果你真的想这样做,只需添加第三个方法(如updateBoth)或将所有这些选项集中到一个方法中,该方法接受基于你想要的模式的参数…

function updateTime($mode){
     if ($mode == "login){}
     else if ($mode == "activity"){}
     else {
       //update both
     }
}

当这样的项目开始时,许多新手程序员通常会直接编写SQL语句。更有经验的程序员,使用其他更复杂的库,如ORM, MVC, N-Tier layer。

你可能想开始使用ORM库,它们支持你提到的"创建一个类似代理的类"answers"使用对象来表示一行的当前状态"。

对象关系映射(orm)库,有时支持"使用对象来表示一行的当前状态"的方法,有时支持"几行或所有行",这取决于你想做什么。

其中一些,允许直接编写SQL代码作为最后的手段,尽管,常见的操作,插入,更新,查询,都是由方法处理的。

如果您需要更改数据库服务器,或者只是更改表或字段的标识符,它们也很有用。或者,当您使用具有相同结构/模式的多个数据库或多个表时。示例:Sales-January, Sales-February.

这些库可能有点复杂,难以理解,但是,一旦你习惯了它们,它们就会帮助你处理更复杂的操作,就像你发布的那个。

我的2美分。