Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->Linux程序设计 ->正文

五个常见 PHP 数据库问题

来源:IBM DW中国 作者:Jack Herrington  时间:2007-04-22 点击: [收藏] [投稿]

这里,我们对数据库进行一次查询,以获得所有的行。代码不复杂,并且它将数据库作为其原有的用途使用。

问题 5:n+1 模式

我真不知有多少次看到过这样的大型应用程序,其中的代码首先检索一些实体(比如说客户),然后来回地一个一个地检索它们,以得到每个实体的详细信息。我们将其称为 n+1 模式,因为查询要执行这么多次 —— 一次查询检索所有实体的列表,然后对于 n 个实体中的每一个执行一次查询。当 n=10 时这还不成其为问题,但是当 n=100 或 n=1000 时呢?然后肯定会出现低效率问题。清单 14 展示了这种模式的一个例子。


清单 14. Schema.sql

DROP TABLE IF EXISTS authors;
CREATE TABLE authors (
  id MEDIUMINT NOT NULL AUTO_INCREMENT,
  name TEXT NOT NULL,
  PRIMARY KEY ( id )
);

DROP TABLE IF EXISTS books;
CREATE TABLE books (
  id MEDIUMINT NOT NULL AUTO_INCREMENT,
  author_id MEDIUMINT NOT NULL,
  name TEXT NOT NULL,
  PRIMARY KEY ( id )
);

INSERT INTO authors VALUES ( null, 'Jack Herrington' );
INSERT INTO authors VALUES ( null, 'Dave Thomas' );

INSERT INTO books VALUES ( null, 1, 'Code Generation in Action' );
INSERT INTO books VALUES ( null, 1, 'Podcasting Hacks' );
INSERT INTO books VALUES ( null, 1, 'PHP Hacks' );
INSERT INTO books VALUES ( null, 2, 'Pragmatic Programmer' );
INSERT INTO books VALUES ( null, 2, 'Ruby on Rails' );
INSERT INTO books VALUES ( null, 2, 'Programming Ruby' );

该模式是可靠的,其中没有任何错误。问题在于访问数据库以找到一个给定作者的所有书籍的代码中,如下所示。


清单 15. Get.php

<?php
require_once('DB.php');

$dsn = 'mysql://root:password@localhost/good_books';
$db =& DB::Connect( $dsn, array() );
if (PEAR::isError($db)) { die($db->getMessage()); }

function get_author_id( $name )
{
  global $db;

  $res = $db->query( "SELECT id FROM authors WHERE name=?",
    array( $name ) );
  $id = null;
  while( $res->fetchInto( $row ) ) { $id = $row[0]; }
  return $id;
}

function get_books( $id )
{
  global $db;

  $res = $db->query( "SELECT id FROM books WHERE author_id=?",
    array( $id ) );
  $ids = array();
  while( $res->fetchInto( $row ) ) { $ids []= $row[0]; }
  return $ids;
}

function get_book( $id )
{
  global $db;

  $res = $db->query( "SELECT * FROM books WHERE id=?", array( $id ) );
  while( $res->fetchInto( $row ) ) { return $row; }
  return null;
}

$author_id = get_author_id( 'Jack Herrington' );
$books = get_books( $author_id );
foreach( $books as $book_id ) {
  $book = get_book( $book_id );
  var_dump( $book );
}
?>

如果您看看下面的代码,您可能会想,“嘿,这才是真正的清楚明了。” 首先,得到作者 id,然后得到书籍列表,然后得到有关每本书的信息。的确,它很清楚明了,但是其高效吗?回答是否定的。看看只是检索 Jack Herrington 的书籍时要执行多少次查询。一次获得 id,另一次获得书籍列表,然后每本书执行一次查询。三本书要执行五次查询!

解决方案是用一个函数来执行大量的查询,如下所示。


清单 16. Get_good.php

<?php
require_once('DB.php');

$dsn = 'mysql://root:password@localhost/good_books';
$db =& DB::Connect( $dsn, array() );
if (PEAR::isError($db)) { die($db->getMessage()); }

function get_books( $name )
{
  global $db;

  $res = $db->query(
    "SELECT books.* FROM authors,books WHERE
      books.author_id=authors.id AND authors.name=?",
      array( $name ) );
  $rows = array();
  while( $res->fetchInto( $row ) ) { $rows []= $row; }
  return $rows;
}

$books = get_books( 'Jack Herrington' );
var_dump( $books );
?>

现在检索列表需要一个快速、单个的查询。这意味着我将很可能必须具有几个这些类型的具有不同参数的方法,但是实在是没有选择。如果您想要具有一个扩展的 PHP 应用程序,那么必须有效地使用数据库,这意味着更智能的查询。

本例的问题是它有点太清晰了。通常来说,这些类型的 n+1n*n 问题要微妙得多。并且它们只有在数据库管理员在系统具有性能问题时在系统上运行查询剖析器时才会出现。

结束语

数据库是强大的工具,就跟所有强大的工具一样,如果您不知道怎么样正确地使用就会滥用它们。识别和解决这些问题的诀窍是更好地理解底层技术。长期以来,我老听到业务逻辑编写人员抱怨,他们不想要必须理解数据库或 SQL 代码。他们把数据库当成对象使用,并疑惑性能为什么如此之差。

他们没有认识到,理解 SQL 对于将数据库从一个困难的必需品转换成强大的联盟是多么重要。如果您每天使用数据库,但是不熟悉 SQL,那么请阅读 The Art of SQL,这本书写得很好,实践性也很强,可以指导您基本了解数据库。

原文链接:

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<

上一页 1 2 3 45 下一页


上一篇:autoconf 和automake生成Makefile文件   下一篇:vi 中的正则表达式

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
·快速编辑Shell命令行
·从2.4到2.6内核发展中的改进
·两个很详细的shell实例
·内核设计篇
·shell技巧
·批量添加用户
·HowtoCreatingandBootingaNewKernelWithautoconf
·利用ip_conntrack表实现封ip的shell脚本,并有简
·30分钟搞定BASH脚本编程!
·Shell初学者的入门知识
推荐文章
·Linux编程:把PHP作为Shell脚本使用
·在Bourneshellscript里要怎么找出最
·企业中的 Wiki、blog 及其他社区工
·Linux 技巧: Bash 测试和比较函数
·借助 UNIX 成为更优秀的博客
·用C语言实现Ping程序功能
·Python anygui 项目预览
·Awk 实例(一)
精彩文章
·使用PHP 快速生成Flash 动画
·Linux程式设计-11.ShellScript(bash
·深入浅出 Linux设备驱动中断处理介
·在Linux高负载下mysql数据库彻底优
·Linux脚本开发数学库在PHP中的重要
·快速编辑Shell命令行
·在Bourneshellscript里要怎么找出最
·Linux编程之:五个常见PHP数据库问
·Linux编程之序列化存储Python对象(
·Bourne again shell (bash) 基本编
·Linux下Patch的应用和制作方法介绍
·Linux系统编程:用PHP执行Root命令
·安装Tomcat服务器,开发JSP
·日本推广Linux可编程机器人以降低成
·Linux程式设计-11.ShellScript(bash
·重燃你的php安全之火
·使用 OpenSSL API 进行安全编程(2
·使用自由软件Rexx 的实现来编写脚本
·技巧:Vimdiff 使用
·Linux操作系统内核对RTC的编程详解
·深入浅出 Linux设备驱动异步通知介
·Shell 编程入门:Linux 解释器原理
·Linux操作系统下守护进程的编程方法
· Linux下的shell编程入门
·利用单元测试对PHP 代码进行检查
·Linux操作系统中用PHP构建网站详解
Power by linux-cn.com 粤ICP备05006655号