PHP:一个巨大的数据库类或几个较小的类?

时间:2010-06-22 22:53:40

标签: php performance oop optimization

对于我正在编写的当前应用程序,我选择将所有数据库功能放在一个类中,因为它允许我保持数据库代码远离业务逻辑,并且如果我们需要切换,则可以轻松替换数据库代码到另一个DBMS。但是,最近我的数据库类变得相当大(EDIT信息:大约53k),我担心由于它的卷而解析这个文件的速度,因为它通常必须为每个请求进行解析。

通常在任何给定时间只有一个或两个不同的“类型”数据库调用(例如,用户系统调用,资产系统调用,地图系统调用,会话系统调用等),因此一个选项I正在考虑将任务分解为一系列数据库对象“切片”,然后根据函数请求在运行时动态加载它们。

另一方面,我担心这样做会导致(a)导致内存中的大量并行执行(即每个切片现在都有查询方法,独立的查询日志等)以及强迫我修改所有现有代码以指向新的,较小的对象或(b)导致相对性能损失,因为我在此功能中反击以使用已编写的代码(例如,将每个切片指向回父母的查询功能以及突然在整个地方使用__call而不是直接方法访问所引起的性能损失。

在这种情况下,更正确的做法是什么?

编辑更多信息:文件大约53kb,目前约有2,350行(并没有完成),虽然这可能被认为是偏斜的,因为我使用扩展的SQL模型来提高可读性,例如

SELECT
    foo,
    bar,
    baz
FROM
    someTable st
    LEFT JOIN someOtherTable sot
        ON st.id = sot.stId
WHERE
    cond > otherCond

有70个查询功能,每个功能执行一些独特的任务,重叠很少(如果我需要两个惊人相似的结果集,我可以简单地忽略每次不需要的东西并重复使用相同的查询)。

编辑:示例功能:

public function alarm_getActiveAlarmsByAsset($tier, $id) {
    if (    !Redacted::checkNumber($tier, $id) 
        ||  $id < 0 
        ||  $tier > Redacted::ASSET_LOWEST_TIER 
        ||  $tier < Redacted::ASSET_TIER_CUSTOMER
    ) {
        return false;
    }

    $sql = "
        SELECT
            alarmId,
            alarmTime,
            server,
            source,
            reason,
            train,
            server_sites.siteId AS `siteId`
        FROM
            alarm_alarms
    ";

    $join = '';

    switch ($tier) {
        case Redacted::ASSET_TIER_CUSTOMER:
            $join = '
                LEFT JOIN red_campus
                    ON red_campus.campId = red_site.campId
            ';
        case Redacted::ASSET_TIER_CAMPUS:
            $join = '
                LEFT JOIN red_site
                    ON red_site.siteId = server_sites.siteId
            ' . $join;
        case Redacted::ASSET_TIER_SITE:
            $join = '
                LEFT JOIN server_sites
                    ON server_sites.servId = alarm_alarms.server
            ' . $join;
    }
    $table = isset(self::$dbTierMap[$tier + 1]) ? self::$dbTierMap[$tier + 1]['table'] : 'server_sites';
    $field = isset(self::$dbTierMap[$tier + 1]) ? self::$dbTierMap[$tier + 1]['parent'] : 'site';
    $sql .= $join . "
        WHERE
                ackId IS NULL
            AND {$table}.{$field}Id = {$id}
    ";

    $r = $this->query($sql);

    if (!$r) {
        return false;
    }

    $alarms = array();
    while ($alarm = mysql_fetch_assoc($r)) {
        $alarms[] = $alarm;
    }
    return $alarms;
}

4 个答案:

答案 0 :(得分:4)

据我了解,您的数据库类基本上包含了在整个应用程序中进行的所有可能的硬编码查询?

实现数据库层抽象的更好方法是将查询抽象为内部一致的格式,并使用模型和数据库适配器将这些转换为实际的SQL。 E.g:

$customer = $Customer->find(array(
    'fields'    => array('name', 'id'),
    'condition' => array('ssn' => $ssn)
));

Customer类映射到特定表,如有必要,可以将架构映射到不同的列:

class Customer extends BaseModel {
    public $table = 'xe_a3_cstmr';
    public $schema = array(
        'name' => 'ze_42_nm',
        …
    );
}

BaseModel将这些抽象的查询转换为真正的SQL,具体取决于它需要与哪个数据库进行通信:

SELECT `xe_a3_cstmr`.`ze_42_nm`, `xe_a3_cstmr`.`…` FROM `xe_a3_cstmr`
WHERE `xe_a3_cstmr`.`ssn` = 123235;

这样,您的数据库层不会随着您在应用中需要进行的每个新查询呈指数级增长,同时仍保持将查询映射到不同数据库的灵活性。这称为ORM。更不用说这实际上提供了更容易的抽象。您只需要编写不同的数据库适配器,而不需要重写每个单独的硬编码查询。

正如Mewp在评论中提出的那样,一个好的起点是Doctrine

答案 1 :(得分:1)

通常,维护许多小班级更容易。对于MySQL(主要用于PHP),有几个类生成器可用:

sourceforge: PHP Class Generator

sourceforge: php Class Generator - PCG

也许你可以在那里找到新的想法。

答案 2 :(得分:0)

在不知道db方案的情况下很难分辨,但是它总是比一个大类更容易维护几个类(例如每个逻辑实体/ db表一个类)

您不应该担心解析时间,因为对数据库的请求(以及任何网络请求)总是需要更长的时间

答案 3 :(得分:0)

如果您担心解析时间而不是代码质量,可以使用一些编译器缓存,例如APC

但是,如果你有一个大班,为了便于阅读,你可能应该将它重构为较小的类。如果您无法在课堂上轻松找到所需内容(例如修改它),那么它可能太大而无法维护。
如果您决定重构,请记住可维护性和代码质量比执行速度更重要(数据库I / O总是比执行代码慢)。

相关问题