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

时间:2014-08-13 15:18:40

标签: php oop optimization mysqli dry

使用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方法所示)。通过使用多个查询,浪费了大量资源并且延迟增加。

有很多方法可以做到这一点,我现在可以想到。其中一些是可怕的,另一些是可用的。

这是一个清单:

  • 手动制作专门的查询,不要使用这些方法。
    • +不会浪费资源。
    • - 降低可维护性。
  • 创建一个类似代理的类,可以在执行它们之前告诉它们优化一组查询。
    • +如果被告知,则创建优化的查询。
    • +可以在课堂上使用方法。
    • - 要指定应优化的传入查询,并告诉它之后执行查询。
    • - 应用程序服务器上的性能很小。
    • - 随着涉及更多外部组件,复杂性增加。
  • 使用对象表示行的当前状态并一次保存。
    • +简单。
    • - 将大量不必要的数据发送到数据库。
    • - 浪费资源。
    • - 如果在获取行后数据发生更改,则会更糟。
  • 使用对象表示行的状态,但仅保存更改的列。
  • ...

在这种情况下,性能,复杂性和可维护性之间的最佳平衡是什么?

3 个答案:

答案 0 :(得分:0)

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

  

在实体上调用persist方法不会立即导致   要在数据库上发出SQL INSERT。学说适用策略   称为“事务性后写”,这意味着它会延迟   大多数SQL命令,直到调用EntityManager#flush()   然后发出所有必要的SQL语句来同步你的对象   以最有效的方式与数据库,单,短   交易,保持参照完整性。

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

答案 1 :(得分:0)

不要先行优化,尤其是以增加复杂性为代价。我认为你对它添加大量开销的想法是错误的。

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

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

答案 2 :(得分:0)

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

您可能想要开始使用ORM库,它们支持“创建类似代理的类”,并使用“使用对象来表示行的当前状态”。

对象关系映射(ORM)库,有时支持“使用对象来表示行的当前状态”方法,有时支持“多行或所有行”,具体取决于您要执行的操作。

其中一些,允许直接编写SQL作为最后的手段,altought,常用操作,插入,更新,查询,由方法处理。

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

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

只需2美分。