Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5096126
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类:

2008-12-23 23:33:52

网站出现了性能问题,查看了一下,是数据库吃不消了。把问题锁定到Zend_Db_Table上。

下面看一下代码:

1.Table.php

abstract class Zend_Db_Table extends Zend_Db_Table_Abstract
{
}

可见是继承Zend_Db_Table_Abstract,那看看Zend_Db_Table_Abstract的构造函数.

2.Abstract.php

     public function __construct($config = array())
    {
            .......................
            .......................
            //前面省略看最关键部分
             $this->_setup();
   }

    protected function _setup()
    {
        $this->_setupDatabaseAdapter();
        $this->_setupTableName();
        $this->_setupMetadata();           //这2个函数可是相当的复杂
        $this->_setupPrimaryKey();    

    }

    protected function _setupMetadata()
    {
        // Assume that metadata will be loaded from cache
        $isMetadataFromCache = true;

        // If $this has no metadata cache but the class has a default metadata cache
        if (null === $this->_metadataCache && null !== self::$_defaultMetadataCache) {
            // Make $this use the default metadata cache of the class
            $this->_setMetadataCache(self::$_defaultMetadataCache);
        }

        // If $this has a metadata cache
        if (null !== $this->_metadataCache) {
            // Define the cache identifier where the metadata are saved
            $cacheId = md5("$this->_schema.$this->_name");
        }

        // If $this has no metadata cache or metadata cache misses
        if (null === $this->_metadataCache || !($metadata = $this->_metadataCache->load($cacheId))) {
            // Metadata are not loaded from cache
            $isMetadataFromCache = false;
            // Fetch metadata from the adapter's describeTable() method

           //下面这句效率可是很低的,最为耗费数据库的

            $metadata = $this->_db->describeTable($this->_name, $this->_schema);

            // If $this has a metadata cache, then cache the metadata
            if (null !== $this->_metadataCache && !$this->_metadataCache->save($metadata, $cacheId)) {
                /**
                 * @see Zend_Db_Table_Exception
                 */
                require_once 'Zend/Db/Table/Exception.php';
                throw new Zend_Db_Table_Exception('Failed saving metadata to metadataCache');
            }
        }

        // Assign the metadata to $this
        $this->_metadata = $metadata;

        // Update the columns
        $this->_cols = array_keys($this->_metadata);

        // Return whether the metadata were loaded from cache
        return $isMetadataFromCache;
    }
我们再看看
describeTable   函数

\Zend\Db\Adapter 下 Mysqli.php

    public function describeTable($tableName, $schemaName = null)
    {
        /**
         * @todo: use INFORMATION_SCHEMA someday when
         * MySQL's implementation isn't too slow.
         */

        if ($schemaName) {
            $sql = 'DESCRIBE ' . $this->quoteIdentifier("$schemaName.$tableName", true);
        } else {
            $sql = 'DESCRIBE ' . $this->quoteIdentifier($tableName, true);
        }

        /**
         * Use mysqli extension API, because DESCRIBE doesn't work
         * well as a prepared statement on MySQL 4.1.
         */
        if ($queryResult = $this->getConnection()->query($sql)) {
            while ($row = $queryResult->fetch_assoc()) {
                $result[] = $row;
            }
            $queryResult->close();
        } else {
            /**
             * @see Zend_Db_Adapter_Mysqli_Exception
             */
            require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
            throw new Zend_Db_Adapter_Mysqli_Exception($this->getConnection()->error);
        }

        $desc = array();

        $row_defaults = array(
            'Length'          => null,
            'Scale'           => null,
            'Precision'       => null,
            'Unsigned'        => null,
            'Primary'         => false,
            'PrimaryPosition' => null,
            'Identity'        => false
        );
        $i = 1;
        $p = 1;
        foreach ($result as $key => $row) {
            $row = array_merge($row_defaults, $row);
            if (preg_match('/unsigned/', $row['Type'])) {
                $row['Unsigned'] = true;
            }
            if (preg_match('/^((?:var)?char)\((\d+)\)/', $row['Type'], $matches)) {
                $row['Type'] = $matches[1];
                $row['Length'] = $matches[2];
            } else if (preg_match('/^decimal\((\d+),(\d+)\)/', $row['Type'], $matches)) {
                $row['Type'] = 'decimal';
                $row['Precision'] = $matches[1];
                $row['Scale'] = $matches[2];
            } else if (preg_match('/^((?:big|medium|small|tiny)?int)\((\d+)\)/', $row['Type'], $matches)) {
                $row['Type'] = $matches[1];
                /**
                 * The optional argument of a MySQL int type is not precision
                 * or length; it is only a hint for display width.
                 */
            }
            if (strtoupper($row['Key']) == 'PRI') {
                $row['Primary'] = true;
                $row['PrimaryPosition'] = $p;
                if ($row['Extra'] == 'auto_increment') {
                    $row['Identity'] = true;
                } else {
                    $row['Identity'] = false;
                }
                ++$p;
            }
            $desc[$this->foldCase($row['Field'])] = array(
                'SCHEMA_NAME'      => null, // @todo
                'TABLE_NAME'       => $this->foldCase($tableName),
                'COLUMN_NAME'      => $this->foldCase($row['Field']),
                'COLUMN_POSITION' => $i,
                'DATA_TYPE'        => $row['Type'],
                'DEFAULT'          => $row['Default'],
                'NULLABLE'         => (bool) ($row['Null'] == 'YES'),
                'LENGTH'           => $row['Length'],
                'SCALE'            => $row['Scale'],
                'PRECISION'        => $row['Precision'],
                'UNSIGNED'         => $row['Unsigned'],
                'PRIMARY'          => $row['Primary'],
                'PRIMARY_POSITION' => $row['PrimaryPosition'],
                'IDENTITY'         => $row['Identity']
            );
            ++$i;
        }
        return $desc;
    }

这个函数执行起来可是够慢的了。^-^


      我用的是Myisam表,这种表采用的是表锁定,在我那个网站上进行这么复杂,这么多的密集查询,不发生了死锁才怪呢?

解决方法:

1.最简单的方法

   把后面2行注释掉,(会有一些功能不能用,不过基本功能可用)

    protected function _setup()
    {
        $this->_setupDatabaseAdapter();
        $this->_setupTableName();
       // $this->_setupMetadata();           //这2个函数可是相当的复杂
       // $this->_setupPrimaryKey();    

    }


2.不用Zend_Db_Table了,或者自己写一个继承类Zend_Db
阅读(2646) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~