`
becoder
  • 浏览: 5002 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

【原】Zend Framework Performance Guide (性能指南) 第一部分

阅读更多

 

最近正在进行针对Zend Framework(本文简称为ZF)的调研工作,本文翻译于ZF最新的官方手册附录E - Zend Framework Performance Guide。水平有限,多有缺点,请多指正。

原文链接:http://framework.zend.com/manual/en/performance.html

我的个人博客链接:http://becoder.cn/?p=119

E.2. Class Loading

任何对ZF应用进行性能分析都会意识到,由于Class loading所导致的性能问题是非常严重的。从大量的class文件载入到那些class-file不能一对一关联的plugin组件。各种各样的include_once和require_once充斥着我们的应用程序,从而导致了的大量的潜在问题,本章节我们提供了一些常见问题的具体解决方案。

E.2.1.  如何优化 Include_path ?

include_path的定义会Class loading的速度略有影响,通常我们可以通过以下四种方式来提高速度:

  1. 使用绝对路径引用(包括基于绝对路径的相对引用)
  2. 减少path的定义数量.
  3. 让ZF的include_path优先级越高越好
  4. 使当前目录在include_path中处于最后的位置,也就是’.’在最后(默认是最先)

E.2.1.1.  使用相对路径

绝对还是相对,这看上去并不像是一个大问题。它们之间的区别在于,如果我们使用相对引用,那么意味着程序无法使用PHP的realpath cache来快速访问文件目录,而绝对路径可以通过cache来提高我们的访问速度。

有两种非常方便的办法来实现绝对引用。第一种方式是我们在php.ini,httpd.conf, .htaccess或者其他的定义方式来通过硬编码的方式来使用绝对引用。其次我们可以在程序中通过PHP的realpath函数来帮助设置include_path为绝对引用。如下例:

$paths = array(
     realpath(dirname(__FILE__) . '/../library'),
     '.'
);
set_include_path(implode(PATH_SEPARATOR, $paths);

或者使用相对路径---当然,它还是相对于某个绝对路径(其实,它依然是绝对的)

define('APPLICATION_PATH', realpath(dirname(__FILE__)));

$paths = array(

    APPLICATION_PATH . '/../library'),

    '.',

);

set_include_path(implode(PATH_SEPARATOR, $paths);
 

E.2.1.2.  减少引用目录数量

在应用程序的解释过程中,扫描引用目录的顺序是由目录在include_path中定义的顺序所决定的。这样就意味着如果所需要引入文件的目录在include_path中定义的越优先,那么扫描引用目录的损耗就会越低。因此,我们可以通过减少引用目录的数量来提高速度。只需要谨慎得校对定义的include_path内容,去除那些无用的目录。

另一个优化措施是合并引用目录,例如,ZF采用了PEAR的命名规范,所以,当系统中需要引用PEAR类库或者其他采用PEAR命名规范的类库时,可以尝试着将这些类库放到同一个引用目录中。

E.2.1.3.  尽量提前引用 ZF 类库所在的 path

从第二点我们可以推断出第三点优化方案,把ZF所在目录定义在include_path最先位置,从而保证应用程序可以在第一次目录扫描中获取到ZF的相应文件。

E.2.1.4.  降低或排除当前目录引用

在很多出现include_path定义的例子中,都会在include_path中定义当前目录(‘.’),而且往往出现在include_path中的第一位(php.ini的默认值)。这的确为引用同一目录下文件提供了极大便利。但是这导致了应用程序会首先遍历当前目录来寻找文件,而在遵循ZF标准的应用程序中,大多数情况下我们根本不需要在当前目录下进行遍历。所以,请将’.’放到include_path的最后一位。

E.2.2.  如何去除不必要的 require 引入 ?

为了优化文件引入过程,PHP提供了延迟加载的优化措施,使用延迟加载,应用程序可以只在需要使用类的时候再进行类的加载,比如对象的初始化,静态方法调用以及静态变量或常量的引用时。PHP通过自动加载机制来实现延迟加载,我们可以通过定义一个或者多个回调函数来实现类名到文件名之间的映射。

然而,在我们的类库的代码中,依然存在并大量使用require_once调用(ZF目前正是如此)。所以现在我们需要停止使用这些require_once从而在最大限度上发挥autoloader所能带来的性能提升。

E.2.2.1.  通过 find sed 命令来停用 require_once

一个简单的办法是,我们可以通过UNIX的sed工具和find命令来注释掉每个require_once的调用。可以试着运行下面的命令来实现(%代表了shell提示符):

% cd path/to/ZendFramework/library

% find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \

  -not -wholename '*/Application.php' -print0 | \

  xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'
 

仅仅一行命令就遍历所有的php文件同时将每个’require_once’替代为’//require_once’。(我们必须保持在Zend_Application 和Zend_Loader_Autoloader文件中的require_once调用,不然会导致程序错误)

我们可以把这个处理命令加到自动编译或者部署流程中,从而提高我们的生产环境下的产品性能。同时需要注意的是,我们必需要将自动加载的过程加到public/index.php文件中,如下例:

require_once 'Zend/Loader/Autoloader.php';

Zend_Loader_Autoloader::getInstance();
 

E.2.3.  如何优化插件加载 ?

大部分组件都支持插件扩展,开发者可以通过自己创建类来和组件协同工作,或者重写已经存在的标准ZF自身插件。插件可以提高框架的灵活性,但代价是,插件载入也会导致性能问题。

插件加载器允许我们注册类前缀与路径的映射,以及在非标准路径下定义类。每个类前缀都可以对应多个路径,运行时,插件加载器会遍历所有的类前缀以及其所对应的所有的路径,检查路径下是否存在可供加载的文件。加载后系统会判断是否包含需要引用的类。我们可以想象一下,这个过程会导致多少次针对物理文件系统的I/O操作。

将你的结论乘以使用的PluginLoader的插件数量,我们可以得出关于插件性能问题的最终结论。在本文发布之时,使用PluginLoader包括以下组件:

  • Zend_Controller_Action_HelperBroker: helpers
  • Zend_Dojo: view helpers, form elements and decorators
  • Zend_File_Transfer: adapters
  • Zend_Filter_Inflector: filters (used by the ViewRenderer action helper and Zend_Layout)
  • Zend_Filter_Input: filters and validators
  • Zend_Form: elements, validators, filters, decorators, captcha and file transfer adapters
  • Zend_Paginator: adapters
  • Zend_View: helpers, filters

现在,我们应该如何来减少如此多的调用次数呢?

E.2.3.1.  使用 PluginLoader 引用文件缓存

ZF 1.7版本中为PluginLoader增加了引用文件缓存机制,这个功能将include_once调用保存到一个文件中,并在bootstrap过程中引用这个文件。虽然这样在我们代码中增加了多余的include_once调用,但同时能保证PluginLoader能够尽早的返回结果,减少引入过程的资源消耗。

E.3. Zend_Db 性能相关

作为数据库抽象层,Zend_DB类库封装了常见SQL操作;Zend_Db_Table则是数据表访问接口,为表级数据库操作提供常用抽象。在这些抽象和所带来的便利背后,有时也会导致额外的性能开销

E.3.1. 如何降低由于获取元数据所导致的性能开销?

为了简便起见,同时在开发过程中可以和库表结构保持变更同步,Zend_Db_Table在内部通过以下方式进行操作,即首次使用库表元数据时,从数据库获得元数据同时保存在成员变量以备之后操作使用。这种方式对性能存在较大影响,无论您底层使用何种数据库,都会导致系统瓶颈的出现。

好消息是,我们有一些方法来解决这个问题:

E.3.1.1. 使用元数据缓存

Zend_Db_Table可以通过使用Zend_Cache来缓存库表元数据。显然这要比每次从数据库中加载元数据要更快更实惠。

可以通过这个链接获得更多关于元数据缓存的内容 Zend_Db_Table documentation includes information on metadata caching .

E.3.1.2. 将元数据硬编码

从ZF 1.7开始,Zend_Db_Table支持可以将库表元数据硬编码到代码中。这属于一种”高级”选项:它的优缺点都是显而易见的,首先可以对性能带来毋庸置疑的提升,同时也意味着提高维护成本,你必须保证你的库表更改与代码中的设定同步。

E.3.2.  Zend_Db_Select所生成的SQL语句总是无法准确得命中库表索引,如何提高?

总体来说,Zend_Db_Select很好得完成了它的设计初衷,但是,当面对一些复杂的SQL查询时,如多表关联或者子查询时,它往往会体现得力不从心。

E.3.2.1. 直接使用自定义优化过的SQL语句

这个问题的正解是自己来写SQL。我们并不需要Zend_Db_Select为我们完成所有的事情。自己设计并且调优出的SQL语句是最正确最值得信赖的选择。

通过执行EXPLAIN命令来分析你的查询(Mysql only?),同时进行反复的测试直到你可以确认语句可以最大限度得发挥你的索引优势,然后将语句定义为成员变量或者类常量来使用它。

如果语句需要传递多个占位符参数,可以通过使用vsprintf() and array_walk()函数来将参数注入到SQL语句中。如下例:

// $adapter is the DB adapter. In Zend_Db_Table, retrieve
// it using $this->getAdapter().
$sql = vsprintf(
    self::SELECT_FOO,
    array_walk($values, array($adapter, 'quoteInto'))
);
分享到:
评论
1 楼 becoder 2010-01-31  
<p>为了方便大家阅读,一楼附上官方原文内容:</p>
<p>E.2. Class Loading
</p>
<div class="sect1" title="E.2. Class Loading">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;">
<a name="performance.classloading"></a>E.2. Class Loading</h2>
</div>
</div>
</div>
<p>Anyone who ever performs profiling of a Zend Framework application will
immediately recognize that class loading is relatively expensive in Zend
Framework. Between the sheer number of class files that need to be loaded for
many components, to the use of plugins that do not have a 1:1 relationship
between their class name and the file system, the various calls to <code class="methodname">include_once()</code> and <code class="methodname">require_once()</code> can be problematic. This chapter intends
to provide some concrete solutions to these issues. </p>
<div class="sect2" title="E.2.1. How can I optimize my include_path?">
<div class="titlepage">
<div>
<div>
<h3 class="title">
<a name="performance.classloading.includepath"></a>E.2.1. How can
I optimize my include_path?</h3>
</div>
</div>
</div>
<p>One trivial optimization you can do to increase the speed of class loading is
to pay careful attention to your include_path. In particular, you should do four
things: use absolute paths (or paths relative to absolute paths), reduce the
number of include paths you define, have your Zend Framework include_path as
early as possible, and only include the current directory path at the end of
your include_path. </p>
<div class="sect3" title="E.2.1.1. Use absolute paths">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.classloading.includepath.abspath"></a>E.2.1.1. Use absolute
paths</h4>
</div>
</div>
</div>
<p>While this may seem a micro-optimization, the fact is that if you don't,
you'll get very little benefit from <acronym class="acronym">PHP</acronym>'s
realpath cache, and as a result, opcode caching will not perform nearly as you
may expect. </p>
<p>There are two easy ways to ensure this. First, you can hardcode the paths in
your <code class="filename">php.ini</code>, <code class="filename">httpd.conf</code>, or <code class="filename">.htaccess</code>.
Second, you can use <acronym class="acronym">PHP</acronym>'s <code class="methodname">realpath()</code> function when setting your include_path: </p>
<pre class="programlisting">$paths = array(
    realpath(dirname(__FILE__) . '/../library'),
    '.',
);
set_include_path(implode(PATH_SEPARATOR, $paths);
</pre>
<p>You <span class="emphasis"><em>can</em></span> use relative paths -- so long as
they are relative to an absolute path: </p>
<pre class="programlisting">define('APPLICATION_PATH', realpath(dirname(__FILE__)));
$paths = array(
    APPLICATION_PATH . '/../library'),
    '.',
);
set_include_path(implode(PATH_SEPARATOR, $paths);
</pre>
<p>However, even so, it's typically a trivial task to simply pass the path to
<code class="methodname">realpath()</code>. </p>
</div>
<div class="sect3" title="E.2.1.2. Reduce the number of include paths you define">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.classloading.includepath.reduce"></a>E.2.1.2. Reduce the number
of include paths you define</h4>
</div>
</div>
</div>
<p>Include paths are scanned in the order in which they appear in the
include_path. Obviously, this means that you'll get a result faster if the file
is found on the first scan rather than the last. Thus, a rather obvious
enhancement is to simply reduce the number of paths in your include_path to only
what you need. Look through each include_path you've defined, and determine if
you actually have any functionality in that path that is used in your
application; if not, remove it. </p>
<p>Another optimization is to combine paths. For instance, Zend Framework
follows <acronym class="acronym">PEAR</acronym> naming conventions; thus, if you
are using <acronym class="acronym">PEAR</acronym> libraries (or libraries from
another framework or component library that follows <acronym class="acronym">PEAR</acronym> CS), try to put all of these libraries on the same
include_path. This can often be achieved by something as simple as symlinking
one or more libraries into a common directory. </p>
</div>
<div class="sect3" title="E.2.1.3. Define your Zend Framework include_path as early as possible">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.classloading.includepath.early"></a>E.2.1.3. Define your Zend
Framework include_path as early as possible</h4>
</div>
</div>
</div>
<p>Continuing from the previous suggestion, another obvious optimization is to
define your Zend Framework include_path as early as possible in your
include_path. In most cases, it should be the first path in the list. This
ensures that files included from Zend Framework are found on the first scan.
</p>
</div>
<div class="sect3" title="E.2.1.4. Define the current directory last, or not at all">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.classloading.includepath.currentdir"></a>E.2.1.4. Define the
current directory last, or not at all</h4>
</div>
</div>
</div>
<p>Most include_path examples show using the current directory, or '.'. This is
convenient for ensuring that scripts in the same directory as the file requiring
them can be loaded. However, these same examples typically show this path item
as the first item in the include_path -- which means that the current directory
tree is always scanned first. In most cases, with Zend Framework applications,
this is not desired, and the path may be safely pushed to the last item in the
list. </p>
<div class="example">
<a name="performance.classloading.includepath.example"></a>
<p class="title"><strong>Example E.1. Example: Optimized include_path</strong></p>
<div class="example-contents">
<p>Let's put all of these suggestions together. Our assumption will be that you
are using one or more <acronym class="acronym">PEAR</acronym> libraries in
conjunction with Zend Framework -- perhaps the PHPUnit and <code class="classname">Archive_Tar</code> libraries -- and that you occasionally need
to include files relative to the current file. </p>
<p>First, we'll create a library directory in our project. Inside that
directory, we'll symlink our Zend Framework's <code class="filename">library/Zend</code> directory, as well as the necessary
directories from our <acronym class="acronym">PEAR</acronym> installation: </p>
<pre class="programlisting">library
    Archive/
    PEAR/
    PHPUnit/
    Zend/
</pre>
<p>This allows us to add our own library code if necessary, while keeping shared
libraries intact. </p>
<p>Next, we'll opt to create our include_path programmatically within our <code class="filename">public/index.php</code> file. This allows us to move our code
around on the file system, without needing to edit the include_path every time.
</p>
<p>We'll borrow ideas from each of the suggestions above: we'll use absolute
paths, as determined using <code class="methodname">realpath()</code>; we'll
include Zend Framework's include path early; we've already consolidated
include_paths; and we'll put the current directory as the last path. In fact,
we're doing really well here -- we're going to end up with only two paths. </p>
<pre class="programlisting">$paths = array(
    realpath(dirname(__FILE__) . '/../library'),
    '.'
);
set_include_path(implode(PATH_SEPARATOR, $paths));
</pre>
</div>
</div>
<br class="example-break">
</div>
</div>
<div class="sect2" title="E.2.2. How can I eliminate unnecessary require_once statements?">
<div class="titlepage">
<div>
<div>
<h3 class="title">
<a name="performance.classloading.striprequires"></a>E.2.2. How
can I eliminate unnecessary require_once statements?</h3>
</div>
</div>
</div>
<p>Lazy loading is an optimization technique designed to push the expensive
operation of loading a class file until the last possible moment -- i.e., when
instantiating an object of that class, calling a static class method, or
referencing a class constant or static property. <acronym class="acronym">PHP</acronym> supports this via autoloading, which allows you to
define one or more callbacks to execute in order to map a class name to a file.
</p>
<p>However, most benefits you may reap from autoloading are negated if your
library code is still performing <code class="methodname">require_once()</code>
calls -- which is precisely the case with Zend Framework. So, the question is:
how can you eliminate those <code class="methodname">require_once()</code> calls
in order to maximize autoloader performance? </p>
<div class="sect3" title="E.2.2.1. Strip require_once calls with find and sed">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.classloading.striprequires.sed"></a>E.2.2.1. Strip require_once
calls with find and sed</h4>
</div>
</div>
</div>
<p>An easy way to strip <code class="methodname">require_once()</code> calls is to
use the <acronym class="acronym">UNIX</acronym> utilities 'find' and 'sed' in
conjunction to comment out each call. Try executing the following statements
(where '%' indicates the shell prompt): </p>
<pre class="programlisting">% cd path/to/ZendFramework/library
% find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \
  -not -wholename '*/Application.php' -print0 | \
  xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'
</pre>
<p>This one-liner (broken into two lines for readability) iterates through each
<acronym class="acronym">PHP</acronym> file and tells it to replace each instance
of 'require_once' with '// require_once', effectively commenting out each such
statement. (It selectively keeps <code class="methodname">require_once()</code>
calls within <code class="classname">Zend_Application</code> and <code class="classname">Zend_Loader_Autoloader</code>, as these classes will fail
without them.) </p>
<p>This command could be added to an automated build or release process
trivially, helping boost performance in your production application. It should
be noted, however, that if you use this technique, you <span class="emphasis"><em>must</em></span> utilize autoloading; you can do that from
your "<code class="filename">public/index.php</code>" file with the following
code: </p>
<pre class="programlisting">require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();
</pre>
</div>
</div>
<div class="sect2" title="E.2.3. How can I speed up plugin loading?">
<div class="titlepage">
<div>
<div>
<h3 class="title">
<a name="performance.classloading.pluginloader"></a>E.2.3. How can
I speed up plugin loading?</h3>
</div>
</div>
</div>
<p>Many components have plugins, which allow you to create your own classes to
utilize with the component, as well as to override existing, standard plugins
shipped with Zend Framework. This provides important flexibility to the
framework, but at a price: plugin loading is a fairly expensive task. </p>
<p>The plugin loader allows you to register class prefix / path pairs, allowing
you to specify class files in non-standard paths. Each prefix can have multiple
paths associated with it. Internally, the plugin loader loops through each
prefix, and then through each path attached to it, testing to see if the file
exists and is readable on that path. It then loads it, and tests to see that the
class it is looking for is available. As you might imagine, this can lead to
many stat calls on the file system. </p>
<p>Multiply this by the number of components that use the PluginLoader, and you
get an idea of the scope of this issue. At the time of this writing, the
following components made use of the PluginLoader: </p>
<div class="itemizedlist">
<ul class="itemizedlist" type="disc">
<li class="listitem">
<p><code class="classname">Zend_Controller_Action_HelperBroker</code>: helpers
</p>
</li>
<li class="listitem">
<p><code class="classname">Zend_Dojo</code>: view helpers, form elements and
decorators </p>
</li>
<li class="listitem">
<p><code class="classname">Zend_File_Transfer</code>: adapters </p>
</li>
<li class="listitem">
<p><code class="classname">Zend_Filter_Inflector</code>: filters (used by the
ViewRenderer action helper and <code class="classname">Zend_Layout</code>) </p>
</li>
<li class="listitem">
<p><code class="classname">Zend_Filter_Input</code>: filters and validators </p>
</li>
<li class="listitem">
<p><code class="classname">Zend_Form</code>: elements, validators, filters,
decorators, captcha and file transfer adapters </p>
</li>
<li class="listitem">
<p><code class="classname">Zend_Paginator</code>: adapters </p>
</li>
<li class="listitem">
<p><code class="classname">Zend_View</code>: helpers, filters </p>
</li>
</ul>
</div>
<p>How can you reduce the number of such calls made? </p>
<div class="sect3" title="E.2.3.1. Use the PluginLoader include file cache">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.classloading.pluginloader.includefilecache"></a>E.2.3.1. Use the
PluginLoader include file cache</h4>
</div>
</div>
</div>
<p>Zend Framework 1.7.0 adds an include file cache to the PluginLoader. This
functionality writes "<code class="methodname">include_once()</code>" calls to a
file, which you can then include in your bootstrap. While this introduces extra
<code class="methodname">include_once()</code> calls to your code, it also ensures
that the PluginLoader returns as early as possible. </p>
<p>The PluginLoader documentation <a class="link" title="Example 30.6. Using the PluginLoader class file include cache" href="zend.loader.pluginloader.html#zend.loader.pluginloader.performance.example">includes
a complete example of its use</a>. </p>
<p> </p>
<p>E.3. Zend_Db Performance
</p>
<div class="sect1" title="E.3. Zend_Db Performance">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both;">
<a name="performance.database"></a>E.3. Zend_Db Performance</h2>
</div>
</div>
</div>
<p><code class="classname">Zend_Db</code> is a database abstraction layer, and is
intended to provide a common <acronym class="acronym">API</acronym> for <acronym class="acronym">SQL</acronym> operations. <code class="classname">Zend_Db_Table</code> is a Table Data Gateway, intended to
abstract common table-level database operations. Due to their abstract nature
and the "magic" they do under the hood to perform their operations, they can
sometimes introduce performance overhead. </p>
<div class="sect2" title="E.3.1. How can I reduce overhead introduced by Zend_Db_Table for retrieving table metadata?">
<div class="titlepage">
<div>
<div>
<h3 class="title">
<a name="performance.database.tableMetadata"></a>E.3.1. How can I
reduce overhead introduced by Zend_Db_Table for retrieving table
metadata?</h3>
</div>
</div>
</div>
<p>In order to keep usage as simple as possible, and also to support constantly
changing schemas during development, <code class="classname">Zend_Db_Table</code>
does some magic under the hood: on first use, it fetches the table schema and
stores it within object members. This operation is typically expensive,
regardless of the database -- which can contribute to bottlenecks in production.
</p>
<p>Fortunately, there are techniques for improving the situation. </p>
<div class="sect3" title="E.3.1.1. Use the metadata cache">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.database.tableMetadata.cache"></a>E.3.1.1. Use the metadata
cache</h4>
</div>
</div>
</div>
<p><code class="classname">Zend_Db_Table</code> can optionally utilize <code class="classname">Zend_Cache</code> to cache table metadata. This is typically
faster to access and less expensive than fetching the metadata from the database
itself. </p>
<p>The <a class="link" title="15.5.12. Caching Table Metadata" href="zend.db.table.html#zend.db.table.metadata.caching"><code class="classname">Zend_Db_Table </code>documentation includes information on
metadata caching</a>. </p>
</div>
<div class="sect3" title="E.3.1.2. Hardcode your metadata in the table definition">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.database.tableMetadata.hardcoding"></a>E.3.1.2. Hardcode your
metadata in the table definition</h4>
</div>
</div>
</div>
<p>As of 1.7.0, <code class="classname">Zend_Db_Table</code> also provides <a class="link" title="15.5.12.1. Hardcoding Table Metadata" href="zend.db.table.html#zend.db.table.metadata.caching.hardcoding">support for
hardcoding metadata in the table definition</a>. This is an advanced use case,
and should only be used when you know the table schema is unlikely to change, or
that you're able to keep the definitions up-to-date. </p>
</div>
</div>
<div class="sect2" title="E.3.2. SQL generated with Zend_Db_Select s not hitting my indexes; how can I make it better?">
<div class="titlepage">
<div>
<div>
<h3 class="title">
<a name="performance.database.select"></a>E.3.2. SQL generated
with Zend_Db_Select s not hitting my indexes; how can I make it
better?</h3>
</div>
</div>
</div>
<p><code class="classname">Zend_Db_Select</code> is relatively good at its job.
However, if you are performing complex queries requiring joins or sub-selects,
it can often be fairly naive. </p>
<div class="sect3" title="E.3.2.1. Write your own tuned SQL">
<div class="titlepage">
<div>
<div>
<h4 class="title">
<a name="performance.database.select.writeyourown"></a>E.3.2.1. Write your own tuned
SQL</h4>
</div>
</div>
</div>
<p>The only real answer is to write your own <acronym class="acronym">SQL</acronym>; <code class="classname">Zend_Db</code> does not
require the usage of <code class="classname">Zend_Db_Select</code>, so providing
your own, tuned <acronym class="acronym">SQL</acronym> select statements is a
perfectly legitimate approach, </p>
<p>Run <code class="constant">EXPLAIN</code> on your queries, and test a variety
of approaches until you can reliably hit your indices in the most performant way
-- and then hardcode the <acronym class="acronym">SQL</acronym> as a class
property or constant. </p>
<p>If the <acronym class="acronym">SQL</acronym> requires variable arguments,
provide placeholders in the <acronym class="acronym">SQL</acronym>, and utilize a
combination of <code class="methodname">vsprintf()</code> and <code class="methodname">array_walk()</code> to inject the values into the <acronym class="acronym">SQL</acronym>: </p>
<pre class="programlisting">// $adapter is the DB adapter. In Zend_Db_Table, retrieve
// it using $this-&gt;getAdapter().
$sql = vsprintf(
    self::SELECT_FOO,
    array_walk($values, array($adapter, 'quoteInto'))
);
</pre>
</div>
</div>
</div>

</div>
</div>
</div>

相关推荐

    Zend Framework 3 Developer's Guide epub

    Zend Framework 3 Developer's Guide 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    zend framework中英文手册.rar

    1. **入门指南**:介绍如何搭建开发环境,创建第一个 Zend Framework 应用。 2. **组件详解**:对每个组件的功能、接口和配置进行详尽解析。 3. **最佳实践**:提供开发过程中应遵循的最佳实践和注意事项。 4. **...

    Zend Framework 3 Developer's Guide azw3

    Zend Framework 3 Developer's Guide 英文azw3 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    ZendFramework-1.10.4-minimal

    由于仅给出了 "ZendFramework-1.10.4-minimal" 这一个文件名,我们可以推测压缩包内可能包含的是 Zend Framework 1.10.4 版本的源代码、库文件、配置文件、文档等基本组成部分,但不包含任何额外的模块或示例应用。...

    Zend Framework Participant Guide

    Zend Framework 考试认证书籍

    ZEND FRAMEWORK 1.11.7 中文参考文档

    Table of Contents •Introduction to Zend Framework •Overview •Installation •Learning Zend Framework •Zend Framework Quick Start •Autoloading in Zend Framework •Plugins in Zend Framework •...

    Zend Framework 2 Application Development

    Zend Framework 2 Application Development is your guide to everything you need to know to build applications of any size for big and small companies alike, whilst using the right components for the job...

    zend framework 中文手册

    描述提到"zend framework zendframework manual 手册,Zend Framework手册 中文版,有一部分还没有汉化",这意味着虽然该手册是中文版本,但可能并非全部内容都已翻译完成,部分原文可能是英文状态。 **Zend ...

    基于Zend Framework 框架的CMS PHP 源代码

    Zend Framework推崇“选择性使用”原则,开发者可以根据项目需求选择使用其中的部分或全部组件,极大地提高了开发效率和代码质量。 **二、CMS系统的核心功能** CMS系统通常包含以下核心功能: 1. **内容创建与...

    Zend Framework 3 Developer's Guide mobi

    Zend Framework 3 Developer's Guide 英文mobi 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    ZendFramework 1.12.9 代码和文档.rar

    1. **下载与解压**:首先,从官方网站或者提供的压缩包"ZendFramework-1.12.9.zip"下载并解压到服务器的适当位置。 2. **环境要求**:确保服务器环境满足PHP 5.2.5或更高版本。 3. **配置自动加载**:通过设置`...

    Zend Framework 2 官方教程汉化版

    Zend Framework 2 官方教程汉化版

    [Zend] Zend Framework 2 0 初学者指南 英文版

    [Packt Publishing] Zend Framework 2 0 初学者指南 英文版 [Packt Publishing] Zend Framework 2 0 by Example Beginner&quot;s Guide E Book ☆ 图书概要:☆ A step by step guide to help you build full ...

    Zend Framework+smarty用法实例详解

    1. 下载并安装Zend Framework:首先需要从Zend Framework官方网站下载所需版本的框架文件,通常有.zip和.tar.gz两种格式可供选择。 2. 目录结构规划:虽然Zend Framework没有强制的目录结构要求,但通常会建议一个...

    Zend Framework实例教程

    本教程聚焦于介绍Zend Framework的核心特性和如何构建一个简单的应用程序,具体为一个新闻管理系统。此教程适用于希望了解和掌握Zend Framework的开发人员。 ##### 安装需求: - **PHP 5**:作为运行环境,Zend ...

    (教你如何使用Zend工具)Zend Framework, A Beginner’s Guide pdf

    《Zend Framework:初学者指南》是一本专门为初学者设计的学习手册,旨在帮助读者快速掌握Zend Framework的核心概念与实践技能。本书由Vikram Vaswani撰写,由McGraw-Hill出版社出版。作为一本权威性的学习资源,它...

    Zend Framework API documentation

    Zend Framework API 文档是一份详尽的资源,专为开发者提供关于 Zend Framework 的技术信息和使用指南。这个框架是用 PHP 开发的,旨在帮助构建高质量、可维护的 Web 应用程序。其 API(应用程序编程接口)文档是...

    ZendFramework中文手册HTML版

    **一、Zend Framework 基础概念** Zend Framework 遵循 Model-View-Controller (MVC) 设计模式,它将应用程序的业务逻辑、数据和用户界面分离开来,使得代码更易于维护和扩展。在 MVC 架构中,Model 负责处理业务...

    ZendFramework最新版本

    这个“最新版本”指的是 Zend Framework 的 1.11.10 版本,它包含了 MVC(Model-View-Controller)架构模式,这是 Web 开发中常用的设计模式,用于分离应用程序的不同部分,提升代码的可读性和可维护性。 1. **MVC ...

Global site tag (gtag.js) - Google Analytics