在使用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层,它将为您处理这个问题,允许您更新对象属性,然后在完成后保存这些更改
http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html在实体上调用持久化方法不会导致立即在数据库上发出SQL INSERT。原则适用于策略称为"事务性后写",这意味着它会延迟大多数SQL命令,直到EntityManager#flush()被调用然后发出所有必要的SQL语句来同步对象用最高效的方式和单一的数据库,短事务,负责维护引用完整性。
不要预先优化,尤其是以增加复杂性为代价。我认为你增加一堆开销的想法是错误的。
如果你真的想这样做,只需添加第三个方法(如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美分。