网站出现了性能问题,查看了一下,是数据库吃不消了。把问题锁定到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
阅读(2659) | 评论(0) | 转发(0) |