代码之家  ›  专栏  ›  技术社区  ›  Dereleased

一个大型数据库类还是几个较小的类?

  •  1
  • Dereleased  · 技术社区  · 16 年前

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

    通常在任何给定时间只进行一个或可能两个不同的数据库调用“类型”(例如,用户系统调用、资产系统调用、映射系统调用、会话系统调用等),因此我考虑的一个选项是将任务拆分为一系列数据库对象“切片”,然后根据乐趣在运行时动态加载这些任务。操作请求。

    另一方面,我担心这样做会导致(a)在内存中大量并行执行(即,每个切片现在都有一个查询方法、一个独立的查询日志等),并迫使我修改所有现有代码以指向新的、较小的对象,或(b)在我回击这个fu时造成相对的性能损失。与已经编写的代码一起工作的特性(例如,让每个切片点回到父级的查询函数,以及突然在整个地方使用uuu调用而不是直接方法访问所导致的性能下降)。

    在这个场景中,什么是更正确的操作过程?

    编辑以获取更多信息:该文件大约为53kb,目前大约有2350行(还没有完成),尽管这可能被认为是歪斜的,因为我使用扩展的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 回复  |  直到 16 年前
        1
  •  0
  •   Mewp    16 年前

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

    但是,如果您有一个大类,那么为了可读性,很可能应该将它重构为较小的类。如果在类中找不到您需要的东西(例如,修改它),那么它可能太大了,无法维护。
    如果您决定重构,请记住可维护性和代码质量是 远的 比执行速度更重要(数据库I/O比执行代码慢)。

        2
  •  4
  •   deceze    16 年前

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

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

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

    客户类映射到一个特定的表,如果需要,可以将架构映射到不同的列:

    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 .

        3
  •  1
  •   FloE    16 年前

    通常情况下,维护许多小类比较容易。对于mysql(主要与php一起使用),有几个类生成器可用:

    sourceforge: PHP Class Generator

    sourceforge: php Class Generator - PCG

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

        4
  •  0
  •   Sergey Eremin    16 年前

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

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

    推荐文章