﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>网络赚钱指南</title>
	<atom:link href="http://blog.nmi.cn/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.nmi.cn</link>
	<description>网赚之家-www.pany.net.cn</description>
	<lastBuildDate>Wed, 01 Feb 2012 08:44:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MySQL 多表查询2</title>
		<link>http://blog.nmi.cn/archives/481</link>
		<comments>http://blog.nmi.cn/archives/481#comments</comments>
		<pubDate>Wed, 01 Feb 2012 08:44:43 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.nmi.cn/?p=481</guid>
		<description><![CDATA[4、删除记录
用如下命令删除表中的一条记录：mysql&#62; delete from mytable where name=′abc′;
DELETE 从表中删除满足由 where 给出的条件的一条记录。再显示一下结果：
mysql&#62; select * from mytable;
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+
&#124; name &#124; sex &#124; birth &#124; birthaddr &#124; single &#124;
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+
&#124; abccs &#124;f &#124; 1977-07-07 &#124; china &#124; y &#124;
&#124; mary &#124;f &#124; 1978-12-12 &#124; usa &#124; NULL &#124;
&#124; tom &#124;m &#124; 1970-09-02 &#124; usa &#124; NULL &#124;
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+
5、删除表：
mysql&#62; drop table ****(表 1 的名字)，*** [...]]]></description>
			<content:encoded><![CDATA[<p>4、删除记录</p>
<p>用如下命令删除表中的一条记录：mysql&gt; delete from mytable where name=′abc′;</p>
<p>DELETE 从表中删除满足由 where 给出的条件的一条记录。再显示一下结果：</p>
<p>mysql&gt; select * from mytable;<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| name | sex | birth | birthaddr | single |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| abccs |f | 1977-07-07 | china | y |<br />
| mary |f | 1978-12-12 | usa | NULL |<br />
| tom |m | 1970-09-02 | usa | NULL |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+</p>
<p>5、删除表：</p>
<p>mysql&gt; drop table ****(表 1 的名字)，*** 表 2 的名字; 可以删除一个或多个表，小心使用。</p>
<p>6、数据库的删除：</p>
<p>mysql&gt; drop database 数据库名; 小心使用。</p>
<p>7、数据库的备份：</p>
<p>退回到 DOS：</p>
<p>mysql&gt; quit</p>
<p>d:\mysqlbin</p>
<p>使用如下命令对数据库 abccs 进行备份：</p>
<p>mysqldump &#8211;opt abccs&gt;abccs.dbb</p>
<p>abccs.dbb 就是你的数据库 abccs 的备份文件。</p>
<p>8、用批处理方式使用 MySQL:</p>
<p>首先建立一个批处理文件 mytest.sql，内容如下：</p>
<p>use abccs;<br />
select * from mytable;<br />
select name,sex from mytable where name=′abccs′;</p>
<p>在 DOS 下运行如下命令：d:mysqlbin mysql &lt; mytest.sql</p>
<p>在屏幕上会显示执行结果。</p>
<p>如果想看结果，而输出结果很多，则可以用这样的命令： mysql &lt; mytest.sql | more</p>
<p>我们还可以将结果输出到一个文件中： mysql &lt; mytest.sql &gt; mytest.out</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/481/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mb_substr和mb_strcut的区别</title>
		<link>http://blog.nmi.cn/archives/477</link>
		<comments>http://blog.nmi.cn/archives/477#comments</comments>
		<pubDate>Wed, 01 Feb 2012 08:31:53 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.nmi.cn/?p=477</guid>
		<description><![CDATA[mb_substr() 函数对英文或中文字符都表示一个单位。
mb_strcut() 函数对中文字符是 3 个单位，英文是 1 个单位。例如：
&#60;?php
$str = &#8220;这样abcd一来&#8221;;
echo &#8220;mb_substr:&#8221;.mb_substr($str, 0, 5, &#8216;utf-8&#8242;);
echo &#8220;&#60;br&#62;&#8221;;
echo &#8220;mb_strcut:&#8221;.mb_strcut($str, 0, 8, &#8216;utf-8&#8242;);
?&#62;
输出结果如下：
mb_substr: 这样abc
mb_strcut:  这样ab
]]></description>
			<content:encoded><![CDATA[<p>mb_substr() 函数对英文或中文字符都表示一个单位。<br />
mb_strcut() 函数对中文字符是 3 个单位，英文是 1 个单位。例如：<br />
&lt;?php<br />
$str = &#8220;这样abcd一来&#8221;;<br />
echo &#8220;mb_substr:&#8221;.mb_substr($str, 0, 5, &#8216;utf-8&#8242;);<br />
echo &#8220;&lt;br&gt;&#8221;;<br />
echo &#8220;mb_strcut:&#8221;.mb_strcut($str, 0, 8, &#8216;utf-8&#8242;);<br />
?&gt;<br />
输出结果如下：<br />
mb_substr: 这样abc<br />
mb_strcut:  这样ab</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/477/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用五种不同的方式截取文件后缀名</title>
		<link>http://blog.nmi.cn/archives/475</link>
		<comments>http://blog.nmi.cn/archives/475#comments</comments>
		<pubDate>Wed, 01 Feb 2012 08:29:15 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.nmi.cn/archives/475</guid>
		<description><![CDATA[/**
 * 写出五种方式来获取文件后缀名称,一个非常容易考试的题目
 */
$filename  = &#8216;www.baidu.com/images/logo.png&#8217;;
//第一种使用strrchr函数进行字符串的截取
echo substr(strrchr($filename,&#8217;.'),1); //先截取.后面的部分，然后再使用substr截取从1开始的字符串则可
//第二种方式使用pathinfo函数进行数组排列
$arr =  pathinfo($filename);
echo $arr['extension'];
//第三种方式使用strrpos函数,查找最后一个.的位置然后再使用substr截取该长度
echo substr($filename,(strrpos($filename,&#8217;.')+1));
//巧妙的使用数组的方式进行获取
$ar = explode(&#8216;.&#8217;,$filename);
echo array_pop($ar);
//第五种则可使用正则表达式了
echo (preg_replace(&#8216;/.*\.(.*[^\.].*)*/iU&#8217;,'\\1&#8242;,$filename)); //此函数非常好用，可以参考学习下。
]]></description>
			<content:encoded><![CDATA[<p>/**<br />
 * 写出五种方式来获取文件后缀名称,一个非常容易考试的题目<br />
 */<br />
$filename  = &#8216;www.baidu.com/images/logo.png&#8217;;<br />
//第一种使用strrchr函数进行字符串的截取<br />
echo substr(strrchr($filename,&#8217;.'),1); //先截取.后面的部分，然后再使用substr截取从1开始的字符串则可<br />
//第二种方式使用pathinfo函数进行数组排列<br />
$arr =  pathinfo($filename);<br />
echo $arr['extension'];<br />
//第三种方式使用strrpos函数,查找最后一个.的位置然后再使用substr截取该长度<br />
echo substr($filename,(strrpos($filename,&#8217;.')+1));<br />
//巧妙的使用数组的方式进行获取<br />
$ar = explode(&#8216;.&#8217;,$filename);<br />
echo array_pop($ar);<br />
//第五种则可使用正则表达式了<br />
echo (preg_replace(&#8216;/.*\.(.*[^\.].*)*/iU&#8217;,'\\1&#8242;,$filename)); //此函数非常好用，可以参考学习下。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/475/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>解决Can&#8217;t connect to MySQL server on &#8216;localhost&#8217; (10048)</title>
		<link>http://blog.nmi.cn/archives/472</link>
		<comments>http://blog.nmi.cn/archives/472#comments</comments>
		<pubDate>Sat, 21 Jan 2012 06:09:10 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://blog.pany.net.cn/?p=472</guid>
		<description><![CDATA[一般见于使用mysql的windows 2003服务器.
错误的出现的原因:
应用程序需要快速释放和创建新连接, 但是由于 TIME_WAIT 中存在的连接超过默认值，导致较低吞吐量.
解决方案:
和本错误密切相关的两个windows的注册表项:TcpTimedWaitDelay和MaxUserPort的值.
TcpTimedWaitDelay 确定 TCP/IP 可释放已关闭连接并重用其资源前, 必须经过的时间. 关闭和释放之间的此时间间隔通称 TIME_WAIT 状态或两倍最大段生命周期（2MSL）状态. 此时间期间, 重新打开到客户机和服务器的连接的成本少于建立新连接. 减少此条目的值允许 TCP/IP 更快地释放已关闭的连接, 为新连接提供更多资源.
MaxUserPort 确定从系统请求任何可用用户端口时所用最大端口数，TCP/IP 可指定的最高端口号. 如果建立 TCP 连接最大端口连接大于 5000, 本地计算机响应以下错误信息WSAENOBUFS (10055): 因为系统缺乏足够缓冲区或者因为队列已满而无法执行套接字上操作, 从而导致应用程序的10048错误.
打开注册表编辑器regedit
TcpTimedWaitDelay 设置:
找到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters 注册表子键
并创建名为 TcpTimedWaitDelay 的新 REG_DWORD 值
设置此值为十进制 30, 十六进制为 0&#215;0000001e
该值等待时间将是 30 秒。
本项的默认值：0xF0(16进制), 等待时间设置为 240 秒
MaxUserPort 设置(增加最大值端口连接):
找到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters 注册表子键
并创建名为 MaxUserPort 的新 REG_DWORD 值
设置此值为十进制最低 32768
该值等待时间将是 30 秒。
重启windows系统。
本项的默认值：5000(十进制)
关闭注册表编辑器, [...]]]></description>
			<content:encoded><![CDATA[<p>一般见于使用mysql的windows 2003服务器.</p>
<p>错误的出现的原因:</p>
<p>应用程序需要快速释放和创建新连接, 但是由于 TIME_WAIT 中存在的连接超过默认值，导致较低吞吐量.</p>
<p>解决方案:<br />
和本错误密切相关的两个windows的注册表项:TcpTimedWaitDelay和MaxUserPort的值.</p>
<p>TcpTimedWaitDelay 确定 TCP/IP 可释放已关闭连接并重用其资源前, 必须经过的时间. 关闭和释放之间的此时间间隔通称 TIME_WAIT 状态或两倍最大段生命周期（2MSL）状态. 此时间期间, 重新打开到客户机和服务器的连接的成本少于建立新连接. 减少此条目的值允许 TCP/IP 更快地释放已关闭的连接, 为新连接提供更多资源.</p>
<p>MaxUserPort 确定从系统请求任何可用用户端口时所用最大端口数，TCP/IP 可指定的最高端口号. 如果建立 TCP 连接最大端口连接大于 5000, 本地计算机响应以下错误信息WSAENOBUFS (10055): 因为系统缺乏足够缓冲区或者因为队列已满而无法执行套接字上操作, 从而导致应用程序的10048错误.</p>
<p>打开注册表编辑器regedit</p>
<p>TcpTimedWaitDelay 设置:<br />
找到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters 注册表子键<br />
并创建名为 TcpTimedWaitDelay 的新 REG_DWORD 值<br />
设置此值为十进制 30, 十六进制为 0&#215;0000001e<br />
该值等待时间将是 30 秒。<br />
本项的默认值：0xF0(16进制), 等待时间设置为 240 秒</p>
<p>MaxUserPort 设置(增加最大值端口连接):<br />
找到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Services\TCPIP\Parameters 注册表子键<br />
并创建名为 MaxUserPort 的新 REG_DWORD 值<br />
设置此值为十进制最低 32768<br />
该值等待时间将是 30 秒。<br />
重启windows系统。<br />
本项的默认值：5000(十进制)</p>
<p>关闭注册表编辑器, 重启windows系统。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/472/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL 多表查询</title>
		<link>http://blog.nmi.cn/archives/469</link>
		<comments>http://blog.nmi.cn/archives/469#comments</comments>
		<pubDate>Wed, 11 Jan 2012 06:06:34 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://blog.pany.net.cn/?p=469</guid>
		<description><![CDATA[在一个数据库中，可能存在多个表，这些表都是相互关联的。我们继续使用前面的例子。前面建立的表中包含了员工的一些基本信息，如姓名、性别、出生日期、出生地。我们再创建一个表，该表用于描述员工所发表的文章，内容包括作者姓名、文章标题、发表日期。
1、查看第一个表 mytable 的内容：
mysql&#62; select * from mytable;
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+
&#124; name &#124; sex &#124; birth &#124; birthaddr &#124;
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+
&#124; abccs &#124;f &#124; 1977-07-07 &#124; china &#124;
&#124; mary &#124;f &#124; 1978-12-12 &#124; usa &#124;
&#124; tom &#124;m &#124; 1970-09-02 &#124; usa &#124;
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+
2、创建第二个表 title （包括作者、文章标题、发表日期）:
mysql&#62; create table title(writer varchar(20) not null,
-&#62; title varchar(40) not null,
-&#62; senddate date);
&#38;nbsp;&#38;nbsp;&#38;nbsp;&#38;nbsp;向该表中填加记录，最后表的内容如下：
&#60;ccid_nobr&#62;
&#60;table width=&#8221;400&#8243; border=&#8221;1&#8243; cellspacing=&#8221;0&#8243; cellpadding=&#8221;2&#8243;
bordercolorlight = [...]]]></description>
			<content:encoded><![CDATA[<p>在一个数据库中，可能存在多个表，这些表都是相互关联的。我们继续使用前面的例子。前面建立的表中包含了员工的一些基本信息，如姓名、性别、出生日期、出生地。我们再创建一个表，该表用于描述员工所发表的文章，内容包括作者姓名、文章标题、发表日期。</p>
<p>1、查看第一个表 mytable 的内容：</p>
<p>mysql&gt; select * from mytable;<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+<br />
| name | sex | birth | birthaddr |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+<br />
| abccs |f | 1977-07-07 | china |<br />
| mary |f | 1978-12-12 | usa |<br />
| tom |m | 1970-09-02 | usa |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+</p>
<p>2、创建第二个表 title （包括作者、文章标题、发表日期）:</p>
<p>mysql&gt; create table title(writer varchar(20) not null,<br />
-&gt; title varchar(40) not null,<br />
-&gt; senddate date);<br />
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;向该表中填加记录，最后表的内容如下：<br />
&lt;ccid_nobr&gt;<br />
&lt;table width=&#8221;400&#8243; border=&#8221;1&#8243; cellspacing=&#8221;0&#8243; cellpadding=&#8221;2&#8243;<br />
bordercolorlight = &#8220;black&#8221; bordercolordark = &#8220;#FFFFFF&#8221; align=&#8221;center&#8221;&gt;<br />
&lt;tr&gt;<br />
&lt;td bgcolor=&#8221;e6e6e6&#8243; &#8220;font-size:9pt&#8221;&gt;<br />
&lt;pre&gt;&lt;ccid_code&gt; mysql&gt; select * from title;<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+<br />
| writer | title | senddate |<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+<br />
| abccs | a1 | 2000-01-23 |<br />
| mary | b1 | 1998-03-21 |<br />
| abccs | a2 | 2000-12-04 |<br />
| tom | c1 | 1992-05-16 |<br />
| tom | c2 | 1999-12-12 |<br />
+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;+<br />
5 rows in set (0.00sec)</p>
<p>3、多表查询</p>
<p>现在我们有了两个表: mytable 和 title。利用这两个表我们可以进行组合查询：</p>
<p>上面例子中，由于作者姓名、性别、文章记录在两个不同表内，因此必须使用组合来进行查询。必须要指定一个表中的记录如何与其它表中的记录进行匹配。</p>
<p>注意：如果第二个表 title 中的 writer 列也取名为 name（与mytable表中的name列相同）而不是 write r时，就必须用 mytable.name 和 title.name 表示，以示区别。</p>
<p>再举一个例子，用于查询文章 a2 的作者、出生地和出生日期：</p>
<p>mysql&gt; select title,writer,birthaddr,birth from mytable,title<br />
-&gt; where mytable.name=title.writer and title=′a2′;<br />
+&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+<br />
| title | writer | birthaddr | birth |<br />
+&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+<br />
| a2 | abccs | china | 1977-07-07 |<br />
+&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;+</p>
<p>修改和备份、批处理</p>
<p>有时我们要对数据库表和数据库进行修改和删除，可以用如下方法实现：</p>
<p>1、增加一列：</p>
<p>如在前面例子中的 mytable 表中增加一列表示是否单身 single:</p>
<p>mysql&gt; alter table mytable add column single char(1);</p>
<p>2、修改记录</p>
<p>将 abccs 的 single 记录修改为“y”：</p>
<p>mysql&gt; update mytable set single=′y′ where name=′abccs′; 现在来看看发生了什么：</p>
<p>mysql&gt; select * from mytable;<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| name | sex | birth | birthaddr | single |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| abccs |f | 1977-07-07 | china | y |<br />
| mary |f | 1978-12-12 | usa | NULL |<br />
| tom |m | 1970-09-02 | usa | NULL |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+</p>
<p>3、增加记录</p>
<p>前面已经讲过如何增加一条记录，为便于查看，重复与此：</p>
<p>mysql&gt; insert into mytable<br />
-&gt; values (′abc′,′f′,′1966-08-17′,′china′,′n′);<br />
Query OK, 1 row affected (0.05 sec)</p>
<p>查看一下：</p>
<p>mysql&gt; select * from mytable;<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| name | sex | birth | birthaddr | single |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+<br />
| abccs |f | 1977-07-07 | china | y |<br />
| mary |f | 1978-12-12 | usa | NULL |<br />
| tom |m | 1970-09-02 | usa | NULL |<br />
| abc |f | 1966-08-17 | china | n |<br />
+&#8212;&#8212;&#8212;-+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8211;+</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/469/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>详细介绍PHP应用提速</title>
		<link>http://blog.nmi.cn/archives/466</link>
		<comments>http://blog.nmi.cn/archives/466#comments</comments>
		<pubDate>Tue, 10 Jan 2012 06:02:21 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.pany.net.cn/?p=466</guid>
		<description><![CDATA[我们都知道，速度快是PHP最大的优点。一般情况下PHP总是具有足够的速度支持Web内容动态生成，许多时候你甚至无法找出比它更快的方法。
　　然而，当你不得不面对庞大的访问量、高负荷的应用、有限的带宽以及 其他各种带来性能瓶颈的因素时，你可能会问问自己是否可以做点什么让网站运行得更好。或许只要加上一个 很不起眼的免费模块，你的PHP应用性能以及Web服务器响应速度就会有显著的改善。
　　本文讨论的就是如何进一 步提高php应用的性能，给用户以更美妙的浏览感受。本文分三个方面(代码优化、缓存、内容压缩)阐述提高 PHP应用性能的各种技术，并介绍各个领域的知名产品。
　　代码优化
　　首先我们来看看代码优化。注意，这里的代码优化可不是指把代码写得更加美观漂亮，因为这恐怕已经是 众所周知没有必要继续讨论了;另外，如果你已经考虑到了速度问题，很可能你早就对PHP的源代码作了一些优化。
　　不过，有些工具却能够自动地帮助我们完成这些繁杂的工作，如Zend Optimizer就是这样一个工具。 Zend Optimizer可以从Zend Technologies免费得到，但你必须同意它的许可约定，注意它不是以 GPL方式发行。Zend Optimizer获取由Zend Engine运行时编译生成的中间代码，并对它进行优化， 从而使得中间代码具有更快的执行效率。
　　Zend Optimizer的安装方法非常简单，你只需下载为自己所用平台提供的预编译版本，把下面两行代 码加入到php.ini，然后重新启动Web服务器即可：
　　zend_optimizer.optimization_level=15
　　zend_extension=&#8221;/path/to/ZendOptimizer.so&#8221;
　　zend_loader.enable=Off
　　这里额外增加的第三行代码是可选的。禁止zend_loader似乎能够让Zend Optimizer的速度更快一点 ，所以在php.ini中加上这行代码是值得的。注意：只有当你不使用Zend Encoder Runtime时，你才 可以禁用zend_loader。
　　缓存
　　如果你想要让自己庞大的PHP应用有更好的性能表现，采用缓存也是一种很好的方法。现在已经有许多缓存 方案可供选择，其中包括：Zend Cache，APC，和Afterburner Cache。
　　所有这些产品都属于“缓存模块”。当第一次出现对.php文件的请求时，它们会在Web服务器内存中保存 PHP的中间代码，此后就用“经过编译”的版本响应后继的请求。这种方法确实能够改善应用的性能，因为它使 得磁盘访问量减低到了最少的程度(代码已经读取和解析)，代码直接在内存中运行使得服务器响应请求的速度大大提高。
　　当然，缓存模块还会监视PHP源文件的变化，必要时重新缓存页面，从而防止了用户得到的页面仍 旧由过时的PHP代码生成。由于缓存模块能够明显地降低服务器的负载、提高PHP应用的响应效率，因此它们非 常适合于负载较大的网站使用。
　　如何选择这些缓存产品
　　Zend Cache是Zend Technologies公司的商业软件，而Zend Technologies就是前面提到的 那个为我们提供PHP引擎和免费Zend Optimizer的公司。Zend Cache确实是名不虚传!对于大型的 PHP页面，你可以感觉到第一次运行之后速度就会有所提高，而且服务器也会有更多的可用资源。遗憾的是这个 产品并不免费，不过在有些情形下它仍旧是物超所值。
　　Afterburner Cache是来自Bware Technologies的免费缓存模块，当前这个产品还是Beta版。 Afterburner Cache的做法看起来与Zend Cache差不多，但它对性能的改善程度(还)不能与 Zend Cache相比，而且它还不能与Zend Optimizer一起工作。
　　APC是Alternative PHP Cache的缩写，它是来自Community Connect的又一个免费缓存模 块。这个产品已经具有足够的稳定性供正式场合使用，而且它看起来也能在很大程度上提高响应请求的速度。
　　内容压缩
　　前面我们讨论了几种提高PHP应用性能的方法，下面来看看使得浏览者感到网站速度太慢的另外一个重要因 素：下载速度。如果PHP应用在内部Intranet上运行，而且每一台客户机都以100 MB/s的速度连接到服务 器，那么下载速度应该不是什么问题。然而，如果服务器还要为慢腾腾的Modem用户提供服务，那么值得考虑内 容压缩。
　　大多数浏览器都根据IETF标准支持用gzip进行内容压缩。这意味着你可以用gzip压缩内容然而发送给 浏览器，由浏览器解压缩数据之后再显示页面，这整个过程对用户来说完全透明。至于服务器端的内容压缩， 现在已经有许多不同的方法可供使用。
　　例如，来自Remote Communications的免费Apache模块mod_gzip就具有为支持这类内容编码的浏览器 [...]]]></description>
			<content:encoded><![CDATA[<p>我们都知道，速度快是PHP最大的优点。一般情况下PHP总是具有足够的速度支持Web内容动态生成，许多时候你甚至无法找出比它更快的方法。</p>
<p>　　然而，当你不得不面对庞大的访问量、高负荷的应用、有限的带宽以及 其他各种带来性能瓶颈的因素时，你可能会问问自己是否可以做点什么让网站运行得更好。或许只要加上一个 很不起眼的免费模块，你的PHP应用性能以及Web服务器响应速度就会有显著的改善。</p>
<p>　　本文讨论的就是如何进一 步提高php应用的性能，给用户以更美妙的浏览感受。本文分三个方面(代码优化、缓存、内容压缩)阐述提高 PHP应用性能的各种技术，并介绍各个领域的知名产品。</p>
<p>　　代码优化</p>
<p>　　首先我们来看看代码优化。注意，这里的代码优化可不是指把代码写得更加美观漂亮，因为这恐怕已经是 众所周知没有必要继续讨论了;另外，如果你已经考虑到了速度问题，很可能你早就对PHP的源代码作了一些优化。</p>
<p>　　不过，有些工具却能够自动地帮助我们完成这些繁杂的工作，如Zend Optimizer就是这样一个工具。 Zend Optimizer可以从Zend Technologies免费得到，但你必须同意它的许可约定，注意它不是以 GPL方式发行。Zend Optimizer获取由Zend Engine运行时编译生成的中间代码，并对它进行优化， 从而使得中间代码具有更快的执行效率。</p>
<p>　　Zend Optimizer的安装方法非常简单，你只需下载为自己所用平台提供的预编译版本，把下面两行代 码加入到php.ini，然后重新启动Web服务器即可：</p>
<p>　　zend_optimizer.optimization_level=15</p>
<p>　　zend_extension=&#8221;/path/to/ZendOptimizer.so&#8221;</p>
<p>　　zend_loader.enable=Off</p>
<p>　　这里额外增加的第三行代码是可选的。禁止zend_loader似乎能够让Zend Optimizer的速度更快一点 ，所以在php.ini中加上这行代码是值得的。注意：只有当你不使用Zend Encoder Runtime时，你才 可以禁用zend_loader。</p>
<p>　　缓存</p>
<p>　　如果你想要让自己庞大的PHP应用有更好的性能表现，采用缓存也是一种很好的方法。现在已经有许多缓存 方案可供选择，其中包括：Zend Cache，APC，和Afterburner Cache。</p>
<p>　　所有这些产品都属于“缓存模块”。当第一次出现对.php文件的请求时，它们会在Web服务器内存中保存 PHP的中间代码，此后就用“经过编译”的版本响应后继的请求。这种方法确实能够改善应用的性能，因为它使 得磁盘访问量减低到了最少的程度(代码已经读取和解析)，代码直接在内存中运行使得服务器响应请求的速度大大提高。</p>
<p>　　当然，缓存模块还会监视PHP源文件的变化，必要时重新缓存页面，从而防止了用户得到的页面仍 旧由过时的PHP代码生成。由于缓存模块能够明显地降低服务器的负载、提高PHP应用的响应效率，因此它们非 常适合于负载较大的网站使用。</p>
<p>　　如何选择这些缓存产品</p>
<p>　　Zend Cache是Zend Technologies公司的商业软件，而Zend Technologies就是前面提到的 那个为我们提供PHP引擎和免费Zend Optimizer的公司。Zend Cache确实是名不虚传!对于大型的 PHP页面，你可以感觉到第一次运行之后速度就会有所提高，而且服务器也会有更多的可用资源。遗憾的是这个 产品并不免费，不过在有些情形下它仍旧是物超所值。</p>
<p>　　Afterburner Cache是来自Bware Technologies的免费缓存模块，当前这个产品还是Beta版。 Afterburner Cache的做法看起来与Zend Cache差不多，但它对性能的改善程度(还)不能与 Zend Cache相比，而且它还不能与Zend Optimizer一起工作。</p>
<p>　　APC是Alternative PHP Cache的缩写，它是来自Community Connect的又一个免费缓存模 块。这个产品已经具有足够的稳定性供正式场合使用，而且它看起来也能在很大程度上提高响应请求的速度。</p>
<p>　　内容压缩</p>
<p>　　前面我们讨论了几种提高PHP应用性能的方法，下面来看看使得浏览者感到网站速度太慢的另外一个重要因 素：下载速度。如果PHP应用在内部Intranet上运行，而且每一台客户机都以100 MB/s的速度连接到服务 器，那么下载速度应该不是什么问题。然而，如果服务器还要为慢腾腾的Modem用户提供服务，那么值得考虑内 容压缩。</p>
<p>　　大多数浏览器都根据IETF标准支持用gzip进行内容压缩。这意味着你可以用gzip压缩内容然而发送给 浏览器，由浏览器解压缩数据之后再显示页面，这整个过程对用户来说完全透明。至于服务器端的内容压缩， 现在已经有许多不同的方法可供使用。</p>
<p>　　例如，来自Remote Communications的免费Apache模块mod_gzip就具有为支持这类内容编码的浏览器 压缩静态Web内容的能力。对于绝大多数静态Web内容，mod_gzip都非常有效。mod_gzip可以方便地编译到 Apache里面，也可以作为DSO使用。据Remote communications公司说，mod_gzip也能够压缩来自mod_php 、mod_perl等的动态内容。</p>
<p>　　我试了一次又一次，但看来还是不行。我看了许多关于mod_gzip的论坛和文章，看 来到了mod_gzip的下一个版本(可能是1.3.14.6f)这个问题有望得到解决。在此之前，我们可以在网站的静态 部分使用mod_gzip。</p>
<p>　　然而有时我们确实需要压缩动态内容，所以必须找找其他办法。有一种办法是使用class.gzip_encode.php ，这是一个可以用来压缩页面内容的PHP类，具体方法是在PHP脚本的开头和末尾调用该类的某些函数。如果要 在网站级实现这个方案，可以从php.ini文件的auto_prepend以及auto_append指令调用这些函数。</p>
<p>　　这种方法虽 然有效，但它无疑为高负载的网站带来了更多的开销。关于如何使用这个类的详细说明，请参见它的源代码。 它的源代码说明相当完善，作者告诉了你所有你必须知道的事情。</p>
<p>　　PHP 4.0.4有一个新的输出缓存句柄ob_gzhandler，它与前面的类相似，但用法不同。使用 ob_gzhandler时要在php.ini中加入的内容如下：</p>
<p>　　output_handler = ob_gzhandler ;</p>
<p>　　这行代码使得PHP激活输出缓存，并压缩它发送出去的所有内容。如果由于某种原因你不想在php.ini中加上这行代码，你还可以通过PHP源文件所在目录的.htaccess文件改变默认的服务器行为(不压缩)，语法如下 ：</p>
<p>　　php_value output_handler ob_gzhandler</p>
<p>　　或者是从PHP代码调用，如下所示：</p>
<p>　　ob_start(&#8220;ob_gzhandler&#8221;);</p>
<p>　　采用输出缓存句柄的方法确实非常有效，而且不会给服务器带来什么特殊的负荷。但必须注意的是，Netscape Communicator对压缩图形的支持不佳，因此除非你能够保证所有用户都使用IE浏览器，否则你 应该禁止压缩JPEG和GIF图形。一般地，对于所有其他文件，这种压缩都有效，但建议你针对各种浏览器都分别 进行测试，特别是当你使用了特殊的插件或者数据查看器时这一点尤其重要。</p>
<p>　　使用前面介绍的各种技术，你能够显著地改善网站的性能表现，但应该注意的是：</p>
<p>　　PHP可能是、也可能不是性能瓶颈所在。务必仔细地观察每一个和应用性能有关的因素，比如数据库等。</p>
<p>　　单纯使用本文技术只能在一定限度之内提高Web服务器的性能。因此在归咎于PHP以及它的缓存之前，不妨看看是否应该升级服务器以及是否可以引入负载平衡技术(后者需要较大的投资)。</p>
<p>　　不要低估内容压缩的作用。虽然你在100 MB/s的LAN连接下看到Web应用响应非常迅速，但使用Modem 连接的用户不会，他们只会抱怨你那100 Kb的HTML页面实在过于庞大。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/466/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysql大数据量处理</title>
		<link>http://blog.nmi.cn/archives/463</link>
		<comments>http://blog.nmi.cn/archives/463#comments</comments>
		<pubDate>Sat, 31 Dec 2011 05:59:29 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://blog.pany.net.cn/?p=463</guid>
		<description><![CDATA[一、概述
分表是个目前算是比较炒的比较流行的概念，特别是在大负载的情况下，分表是一个良好分散数据库压力的好方法。
首先要了解为什么要分表，分表的好处是什么。我们先来大概了解以下一个数据库执行SQL的过程：
接收到SQL &#8211;&#62; 放入SQL执行队列 &#8211;&#62; 使用分析器分解SQL &#8211;&#62; 按照分析结果进行数据的提取或者修改 &#8211;&#62; 返回处理结果
当然，这个流程图不一定正确，这只是我自己主观意识上这么我认为。那么这个处理过程当中，最容易出现问题的是什么？就是说，如果前一个SQL没有执行完毕的话，后面的SQL是不会执行的，因为为了保证数据的完整性，必须对数据表文件进行锁定，包括共享锁和独享锁两种锁定。共享锁是在锁定的期间，其它线程也可以访问这个数据文件，但是不允许修改操作，相应的，独享锁就是整个文件就是归一个线程所有，其它线程无法访问这个数据文件。一般MySQL中最快的存储引擎MyISAM，它是基于表锁定的，就是说如果一锁定的话，那么整个数据文件外部都无法访问，必须等前一个操作完成后，才能接收下一个操作，那么在这个前一个操作没有执行完成，后一个操作等待在队列里无法执行的情况叫做阻塞，一般我们通俗意义上叫做“锁表”。
锁表直接导致的后果是什么？就是大量的SQL无法立即执行，必须等队列前面的SQL全部执行完毕才能继续执行。这个无法执行的SQL就会导致没有结果，或者延迟严重，影响用户体验。
特别是对于一些使用比较频繁的表，比如SNS系统中的用户信息表、论坛系统中的帖子表等等，都是访问量大很大的表，为了保证数据的快速提取返回给用户，必须使用一些处理方式来解决这个问题，这个就是我今天要聊到的分表技术。
分表技术顾名思义，就是把若干个存储相同类型数据的表分成几个表分表存储，在提取数据的时候，不同的用户访问不同的表，互不冲突，减少锁表的几率。比如，目前保存用户分表有两个表，一个是user_1表，还有一个是 user_2 表，两个表保存了不同的用户信息，user_1 保存了前10万的用户信息，user_2保存了后10万名用户的信息，现在如果同时查询用户 heiyeluren1 和 heiyeluren2 这个两个用户，那么就是分表从不同的表提取出来，减少锁表的可能。
我下面要讲述的两种分表方法我自己都没有实验过，不保证准确能用，只是提供一个设计思路。下面关于分表的例子我假设是在一个贴吧系统的基础上来进行处理和构建的。（如果没有用过贴吧的用户赶紧Google一下）
二、基于基础表的分表处理
这个基于基础表的分表处理方式大致的思想就是：一个主要表，保存了所有的基本信息，如果某个项目需要找到它所存储的表，那么必须从这个基础表中查找出对应的表名等项目，好直接访问这个表。如果觉得这个基础表速度不够快，可以完全把整个基础表保存在缓存或者内存中，方便有效的查询。
我们基于贴吧的情况，构建假设如下的3张表：
1. 贴吧版块表: 保存贴吧中版块的信息
2. 贴吧主题表：保存贴吧中版块中的主题信息，用于浏览
3. 贴吧回复表：保存主题的原始内容和回复内容
“贴吧版块表”包含如下字段：
版块ID       board_id          int(10)
版块名称    board_name      char(50)
子表ID       table_id            smallint(5)
产生时间    created             datetime
“贴吧主题表”包含如下字段：
主题ID          topic_id        int(10)
主题名称        topic_name     char(255)
版块ID          board_id          int(10)
创建时间       created           datetime
“贴吧回复表”的字段如下：
回复ID        reply_id           int(10)
回复内容      reply_text        text
主题ID        topic_id           int(10)
版块ID        board_id         int(10)
创建时间      created            datetime
那么上面保存了我们整个贴吧中的表结构信息，三个表对应的关系是：
版块 &#8211;&#62; 多个主题
主题 &#8211;&#62; 多个回复
那么就是说，表文件大小的关系是：
版块表文件 &#60; 主题表文件 &#60; 回复表文件
所以基本可以确定需要对主题表和回复表进行分表，已增加我们数据检索查询更改时候的速度和性能。
看了上面的表结构，会明显发现，在“版块表”中保存了一个&#8221;table_id&#8221;字段，这个字段就是用于保存一个版块对应的主题和回复都是分表保存在什么表里的。
比如我们有一个叫做“PHP”的贴吧，board_id是1，子表ID也是1，那么这条记录就是：
board_id &#124; [...]]]></description>
			<content:encoded><![CDATA[<p>一、概述<br />
分表是个目前算是比较炒的比较流行的概念，特别是在大负载的情况下，分表是一个良好分散数据库压力的好方法。<br />
首先要了解为什么要分表，分表的好处是什么。我们先来大概了解以下一个数据库执行SQL的过程：<br />
接收到SQL &#8211;&gt; 放入SQL执行队列 &#8211;&gt; 使用分析器分解SQL &#8211;&gt; 按照分析结果进行数据的提取或者修改 &#8211;&gt; 返回处理结果<br />
当然，这个流程图不一定正确，这只是我自己主观意识上这么我认为。那么这个处理过程当中，最容易出现问题的是什么？就是说，如果前一个SQL没有执行完毕的话，后面的SQL是不会执行的，因为为了保证数据的完整性，必须对数据表文件进行锁定，包括共享锁和独享锁两种锁定。共享锁是在锁定的期间，其它线程也可以访问这个数据文件，但是不允许修改操作，相应的，独享锁就是整个文件就是归一个线程所有，其它线程无法访问这个数据文件。一般MySQL中最快的存储引擎MyISAM，它是基于表锁定的，就是说如果一锁定的话，那么整个数据文件外部都无法访问，必须等前一个操作完成后，才能接收下一个操作，那么在这个前一个操作没有执行完成，后一个操作等待在队列里无法执行的情况叫做阻塞，一般我们通俗意义上叫做“锁表”。<br />
锁表直接导致的后果是什么？就是大量的SQL无法立即执行，必须等队列前面的SQL全部执行完毕才能继续执行。这个无法执行的SQL就会导致没有结果，或者延迟严重，影响用户体验。<br />
特别是对于一些使用比较频繁的表，比如SNS系统中的用户信息表、论坛系统中的帖子表等等，都是访问量大很大的表，为了保证数据的快速提取返回给用户，必须使用一些处理方式来解决这个问题，这个就是我今天要聊到的分表技术。<br />
分表技术顾名思义，就是把若干个存储相同类型数据的表分成几个表分表存储，在提取数据的时候，不同的用户访问不同的表，互不冲突，减少锁表的几率。比如，目前保存用户分表有两个表，一个是user_1表，还有一个是 user_2 表，两个表保存了不同的用户信息，user_1 保存了前10万的用户信息，user_2保存了后10万名用户的信息，现在如果同时查询用户 heiyeluren1 和 heiyeluren2 这个两个用户，那么就是分表从不同的表提取出来，减少锁表的可能。<br />
我下面要讲述的两种分表方法我自己都没有实验过，不保证准确能用，只是提供一个设计思路。下面关于分表的例子我假设是在一个贴吧系统的基础上来进行处理和构建的。（如果没有用过贴吧的用户赶紧Google一下）<br />
二、基于基础表的分表处理<br />
这个基于基础表的分表处理方式大致的思想就是：一个主要表，保存了所有的基本信息，如果某个项目需要找到它所存储的表，那么必须从这个基础表中查找出对应的表名等项目，好直接访问这个表。如果觉得这个基础表速度不够快，可以完全把整个基础表保存在缓存或者内存中，方便有效的查询。<br />
我们基于贴吧的情况，构建假设如下的3张表：<br />
1. 贴吧版块表: 保存贴吧中版块的信息<br />
2. 贴吧主题表：保存贴吧中版块中的主题信息，用于浏览<br />
3. 贴吧回复表：保存主题的原始内容和回复内容<br />
“贴吧版块表”包含如下字段：<br />
版块ID       board_id          int(10)<br />
版块名称    board_name      char(50)<br />
子表ID       table_id            smallint(5)<br />
产生时间    created             datetime<br />
“贴吧主题表”包含如下字段：<br />
主题ID          topic_id        int(10)<br />
主题名称        topic_name     char(255)<br />
版块ID          board_id          int(10)<br />
创建时间       created           datetime<br />
“贴吧回复表”的字段如下：<br />
回复ID        reply_id           int(10)<br />
回复内容      reply_text        text<br />
主题ID        topic_id           int(10)<br />
版块ID        board_id         int(10)<br />
创建时间      created            datetime<br />
那么上面保存了我们整个贴吧中的表结构信息，三个表对应的关系是：<br />
版块 &#8211;&gt; 多个主题<br />
主题 &#8211;&gt; 多个回复<br />
那么就是说，表文件大小的关系是：<br />
版块表文件 &lt; 主题表文件 &lt; 回复表文件<br />
所以基本可以确定需要对主题表和回复表进行分表，已增加我们数据检索查询更改时候的速度和性能。<br />
看了上面的表结构，会明显发现，在“版块表”中保存了一个&#8221;table_id&#8221;字段，这个字段就是用于保存一个版块对应的主题和回复都是分表保存在什么表里的。<br />
比如我们有一个叫做“PHP”的贴吧，board_id是1，子表ID也是1，那么这条记录就是：<br />
board_id | board_name | table_id | created<br />
1 | PHP | 1 | 2007-01-19 00:30:12<br />
相应的，如果我需要提取“PHP”吧里的所有主题，那么就必须按照表里保存的table_id来组合一个存储了主题的表名称，比如我们主题表的前缀是“topic_”，那么组合出来“PHP”吧对应的主题表应该是：“topic_1”，那么我们执行：<br />
SELECT * FROM topic_1 WHERE board_id = 1 ORDER BY topic_id DESC LIMIT 10<br />
这样就能够获取这个主题下面回复列表，方便我们进行查看，如果需要查看某个主题下面的回复，我们可以继续使用版块表中保存的“table_id”来进行查询。比如我们回复表的前缀是“reply_”，那么就可以组合出“PHP”吧的ID为1的主题的回复：<br />
SELECT * FROM reply_1 WHERE topic_id = 1 ORDER BY reply_id DESC LIMIT 10<br />
这里，我们能够清晰的看到，其实我们这里使用了基础表，基础表就是我们的版块表。那么相应的，肯定会说：基础表的数据量大了以后如何保证它的速度和效率？<br />
当然，我们就必须使得这个基础表保持最好的速度和性能，比如，可以采用MySQL的内存表来存储，或者保存在内存当中，比如Memcache之类的内存缓存等等，可以按照实际情况来进行调整。<br />
一般基于基础表的分表机制在SNS、交友、论坛等Web2.0网站中是个比较不错的解决方案，在这些网站中，完全可以单独使用一个表来来保存基本标识和目标表之间的关系。使用表保存对应关系的好处是以后扩展非常方便，只需要增加一个表记录。<br />
【优势】增加删除节点非常方便，为后期升级维护带来很大便利<br />
【劣势】需要增加表或者对某一个表进行操作，还是无法离开数据库，会产生瓶颈<br />
三、基于Hash算法的分表处理<br />
我们知道Hash表就是通过某个特殊的Hash算法计算出的一个值，这个值必须是惟一的，并且能够使用这个计算出来的值查找到需要的值，这个叫做哈希表。<br />
我们在分表里的hash算法跟这个思想类似：通过一个原始目标的ID或者名称通过一定的hash算法计算出数据存储表的表名，然后访问相应的表。<br />
继续拿上面的贴吧来说，每个贴吧有版块名称和版块ID，那么这两项值是固定的，并且是惟一的，那么我们就可以考虑通过对这两项值中的一项进行一些运算得出一个目标表的名称。<br />
现在假如我们针对我们这个贴吧系统，假设系统最大允许1亿条数据，考虑每个表保存100万条记录，那么整个系统就不超过100个表就能够容纳。按照这个标准，我们假设在贴吧的版块ID上进行hash，获得一个key值，这个值就是我们的表名，然后访问相应的表。<br />
我们构造一个简单的hash算法：<br />
function get_hash($id){<br />
     $str = bin2hex($id);<br />
     $hash = substr($str, 0, 4);<br />
     if (strlen($hash)&lt;4){<br />
         $hash = str_pad($hash, 4, &#8220;0&#8243;);<br />
     }<br />
     return $hash;<br />
}<br />
算法大致就是传入一个版块ID值，然后函数返回一个4位的字符串，如果字符串长度不够，使用0进行补全。<br />
比如：get_hash(1)，输出的结果是“3100”，输入：get_hash(23819)，得到的结果是：3233，那么我们经过简单的跟表前缀组合，就能够访问这个表了。那么我们需要访问ID为1的内容时候哦，组合的表将是：topic_3100、reply_3100，那么就可以直接对目标表进行访问了。<br />
当然，使用hash算法后，有部分数据是可能在同一个表的，这一点跟hash表不同，hash表是尽量解决冲突，我们这里不需要，当然同样需要预测和分析表数据可能保存的表名。<br />
如果需要存储的数据更多，同样的，可以对版块的名字进行hash操作，比如也是上面的二进制转换成十六进制，因为汉字比数字和字母要多很多，那么重复几率更小，但是可能组合成的表就更多了，相应就必须考虑一些其它的问题。<br />
归根结底，使用hash方式的话必须选择一个好的hash算法，才能生成更多的表，然数据查询的更迅速。<br />
【优点hash算法直接得出目标表名称，效率很高】通过<br />
【劣势】扩展性比较差，选择了一个hash算法，定义了多少数据量，以后只能在这个数据量上跑，不能超过过这个数据量，可扩展性稍差<br />
四、其它问题<br />
1. 搜索问题<br />
现在我们已经进行分表了，那么就无法直接对表进行搜索，因为你无法对可能系统中已经存在的几十或者几百个表进行检索，所以搜索必须借助第三方的组件来进行，比如Lucene作为站内搜索引擎是个不错的选择。<br />
2. 表文件问题<br />
我们知道MySQL的MyISAM引擎每个表都会生成三个文件，*.frm、*.MYD、*.MYI 三个文件，分表用来保存表结构、表数据和表索引。Linux下面每个目录下的文件数量最好不要超过1000个，不然检索数据将更慢，那么每个表都会生成三个文件，相应的如果分表超过300个表，那么将检索非常慢，所以这时候就必须再进行分，比如在进行数据库的分离。<br />
使用基础表，我们可以新增加一个字段，用来保存这个表保存在什么数据。使用Hash的方式，我们必须截取hash值中第几位来作为数据库的名字。这样，完好的解决这个问题。<br />
五、总结<br />
在大负载应用当中，数据库一直是个很重要的瓶颈，必须要突破，本文讲解了两种分表的方式，希望对很多人能够有启发的作用。当然，本文代码和设想没有经过任何代码测试，所以无法保证设计的完全准确实用，具体还是需要读者在使用过程当中认真分析实施。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/463/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>优秀的PHP开发者是怎样炼成的？</title>
		<link>http://blog.nmi.cn/archives/460</link>
		<comments>http://blog.nmi.cn/archives/460#comments</comments>
		<pubDate>Mon, 26 Dec 2011 05:50:01 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.pany.net.cn/?p=460</guid>
		<description><![CDATA[　PHP是一门高效的网络编程语言，由于它具有编写灵活、运行快速等优点，迅速成为Web程序员的首选语言。那么怎样才能成为一个优秀的PHP开发者呢?
　　要成为一名PHP编程高手并不容易，并不像很多人想象的那样，只要能够飞快地编写几条简单的代码去解决一个复杂的问题就是PHP编程高手了，真正的PHP高手还需要考虑更多的其它问题。以下三条准则是一名成熟的PHP程序员在编程中应该首先遵循的准则。
　　◆懒惰是金
　　◆编写漂亮的代码
　　◆追求程序的速度，而不是编程的速度
　　懒惰是金
　　做一个懒惰的程序员吗?这个想法太奇怪了!因为这个世界上最忙碌的人可能就是计算机程序员了。但正是因为程序员太忙了，所以才应该在编程时学会偷懒。对于一个程序员来说，懒惰的方法有两种：
　　其一，大胆使用现成的别人的程序代码，把这些代码融入到你自己的程序或者项目中去。其二是编写一些有用的代码建立一个函数库，在将来编写程序时可以顺手拈来，省去了许多重复的劳动，自然就可以懒惰一点了。这两种偷懒的方法都非常适合PHP程序员了。
　　首先，PHP是在自由开放的环境中诞生和成长的一门语言。在世界各地，有成千上万的程序员，他们一直在为PHP的完美而不断奋斗，他们也愿意和别人分享自己的聪明才智和自己编写的代码。你每天都可以从一些PHP网站、邮件列表、新闻组发现大量的优秀的程序代码。
　　这样说，我并不是鼓励你整天等着让别人为你编写代码，但是你可以“站在伟人的肩膀上”，充分发扬“拿来主义”，聪明地应用别人的程序代码可以节省你大量时间。其次，在PHP中，你可以方便地建立自己的函数库，这样可以在你以后编写程序时省去很多麻烦。
　　下面笔者为大家介绍几个通用的函数，这些函数有的来自网上的一些开放源代码的项目，有的精选自邮件列表。如果你能把它们加入到你自己的函数库中，迟早你将会发现自己受益无穷。
　　1.通用数据库处理函数
　　和其它的CGI函数相比，PHP的优点之一是具有很强大的数据库处理能力。但是，在PHP中，对于不同的数据库都使用一些特定的函数来专门处理，缺少通用的数据库处理函数。这大大降低了程序代码的可移植性，这也为初学编程的朋友带来了很多不便。
　　在网上，许多程序员都通过封装类解决了这个问题。他们编写了统一的函数用来处理任何流行的数据库——不管是在Linux世界深受欢迎的Mysql还是在Windows平台上广泛流行的SqlServer。
　　就笔者个人来说，非常喜欢使用这些函数，因为可以直接使用一些简单的诸如”query”、”next_record”之类的函数，而不需要考虑数据库 的连接、数据库句柄这些复杂的东西，更不需要考虑使用的是何种数据库。如果你需要这些函数，你可以通过访问以下的几个网址而得到：
　　◆http://phplib.netuse.de/
　　◆http://phpclasses.UpperDesign.com/browse.html/package/20
　　◆http://phpdb.linuxbox.com/
　　2.变量调试函数
　　PHP程序的调试一直是一件让人头疼的事，它既不像VB等高级语言那样有集成的编译调试环境，也不想Perl那样可以在Linux或者DOS环境下直 接运行。其实，我们完全可以通过灵活地使用echo语句来完成对PHP的调试工作。下面的几个函数可以让你随时查看程序中任何变量的类型及其值。
　　function ss_array_as_string (&#38;$array, $column = 0) {
　　$str = “Array(n”;
　　while(list($var, $val) = each($array)){
　　for ($i = 0; $i &#60; $column+1; $i++){
　　$str .= “    ”;
　　}
　　$str .= $var. ==&#62; ;
　　$str .= ss_as_string($val, $column+1).” n”;
　　}
　　for ($i = 0; $i &#60; $column; $i++){
　　$str .= “    ”;
　　}
　　return $str.);
　　}
　　function ss_object_as_string (&#38;$object, $column = 0) {
　　if (empty($object-&#62;classname)) {
　　return “$object”;
　　}
　　else {
　　$str = $object-&#62;classname.”( [...]]]></description>
			<content:encoded><![CDATA[<p>　PHP是一门高效的网络编程语言，由于它具有编写灵活、运行快速等优点，迅速成为Web程序员的首选语言。那么怎样才能成为一个优秀的PHP开发者呢?</p>
<p>　　要成为一名PHP编程高手并不容易，并不像很多人想象的那样，只要能够飞快地编写几条简单的代码去解决一个复杂的问题就是PHP编程高手了，真正的PHP高手还需要考虑更多的其它问题。以下三条准则是一名成熟的PHP程序员在编程中应该首先遵循的准则。</p>
<p>　　◆懒惰是金</p>
<p>　　◆编写漂亮的代码</p>
<p>　　◆追求程序的速度，而不是编程的速度</p>
<p>　　懒惰是金</p>
<p>　　做一个懒惰的程序员吗?这个想法太奇怪了!因为这个世界上最忙碌的人可能就是计算机程序员了。但正是因为程序员太忙了，所以才应该在编程时学会偷懒。对于一个程序员来说，懒惰的方法有两种：</p>
<p>　　其一，大胆使用现成的别人的程序代码，把这些代码融入到你自己的程序或者项目中去。其二是编写一些有用的代码建立一个函数库，在将来编写程序时可以顺手拈来，省去了许多重复的劳动，自然就可以懒惰一点了。这两种偷懒的方法都非常适合PHP程序员了。</p>
<p>　　首先，PHP是在自由开放的环境中诞生和成长的一门语言。在世界各地，有成千上万的程序员，他们一直在为PHP的完美而不断奋斗，他们也愿意和别人分享自己的聪明才智和自己编写的代码。你每天都可以从一些PHP网站、邮件列表、新闻组发现大量的优秀的程序代码。</p>
<p>　　这样说，我并不是鼓励你整天等着让别人为你编写代码，但是你可以“站在伟人的肩膀上”，充分发扬“拿来主义”，聪明地应用别人的程序代码可以节省你大量时间。其次，在PHP中，你可以方便地建立自己的函数库，这样可以在你以后编写程序时省去很多麻烦。</p>
<p>　　下面笔者为大家介绍几个通用的函数，这些函数有的来自网上的一些开放源代码的项目，有的精选自邮件列表。如果你能把它们加入到你自己的函数库中，迟早你将会发现自己受益无穷。</p>
<p>　　1.通用数据库处理函数</p>
<p>　　和其它的CGI函数相比，PHP的优点之一是具有很强大的数据库处理能力。但是，在PHP中，对于不同的数据库都使用一些特定的函数来专门处理，缺少通用的数据库处理函数。这大大降低了程序代码的可移植性，这也为初学编程的朋友带来了很多不便。</p>
<p>　　在网上，许多程序员都通过封装类解决了这个问题。他们编写了统一的函数用来处理任何流行的数据库——不管是在Linux世界深受欢迎的Mysql还是在Windows平台上广泛流行的SqlServer。</p>
<p>　　就笔者个人来说，非常喜欢使用这些函数，因为可以直接使用一些简单的诸如”query”、”next_record”之类的函数，而不需要考虑数据库 的连接、数据库句柄这些复杂的东西，更不需要考虑使用的是何种数据库。如果你需要这些函数，你可以通过访问以下的几个网址而得到：</p>
<p>　　◆http://phplib.netuse.de/</p>
<p>　　◆http://phpclasses.UpperDesign.com/browse.html/package/20</p>
<p>　　◆http://phpdb.linuxbox.com/</p>
<p>　　2.变量调试函数</p>
<p>　　PHP程序的调试一直是一件让人头疼的事，它既不像VB等高级语言那样有集成的编译调试环境，也不想Perl那样可以在Linux或者DOS环境下直 接运行。其实，我们完全可以通过灵活地使用echo语句来完成对PHP的调试工作。下面的几个函数可以让你随时查看程序中任何变量的类型及其值。</p>
<p>　　function ss_array_as_string (&amp;$array, $column = 0) {</p>
<p>　　$str = “Array(n”;</p>
<p>　　while(list($var, $val) = each($array)){</p>
<p>　　for ($i = 0; $i &lt; $column+1; $i++){</p>
<p>　　$str .= “    ”;</p>
<p>　　}</p>
<p>　　$str .= $var. ==&gt; ;</p>
<p>　　$str .= ss_as_string($val, $column+1).” n”;</p>
<p>　　}</p>
<p>　　for ($i = 0; $i &lt; $column; $i++){</p>
<p>　　$str .= “    ”;</p>
<p>　　}</p>
<p>　　return $str.);</p>
<p>　　}</p>
<p>　　function ss_object_as_string (&amp;$object, $column = 0) {</p>
<p>　　if (empty($object-&gt;classname)) {</p>
<p>　　return “$object”;</p>
<p>　　}</p>
<p>　　else {</p>
<p>　　$str = $object-&gt;classname.”( n”;</p>
<p>　　while (list(,$var) = each($object-&gt;persistent_slots)) {</p>
<p>　　for ($i = 0; $i &lt; $column; $i++){</p>
<p>　　$str .= “    ”;</p>
<p>　　}</p>
<p>　　global $$var;</p>
<p>　　$str .= $var. ==&gt; ;</p>
<p>　　$str .= ss_as_string($$var, column+1).” n”;</p>
<p>　　}</p>
<p>　　for ($i = 0; $i &lt; $column; $i++){</p>
<p>　　$str .= “    ”;</p>
<p>　　}</p>
<p>　　return $str.);</p>
<p>　　}</p>
<p>　　}</p>
<p>　　function ss_as_string (&amp;$thing, $column = 0) {</p>
<p>　　if (is_object($thing)) {</p>
<p>　　return ss_object_as_string($thing, $column);</p>
<p>　　}</p>
<p>　　elseif (is_array($thing)) {</p>
<p>　　return ss_array_as_string($thing, $column);</p>
<p>　　}</p>
<p>　　elseif (is_double($thing)) {</p>
<p>　　return “Double(“.$thing.”)”;</p>
<p>　　}</p>
<p>　　elseif (is_long($thing)) {</p>
<p>　　return “Long(“.$thing.”)”;</p>
<p>　　}</p>
<p>　　elseif (is_string($thing)) {</p>
<p>　　return “String(“.$thing.”)”;</p>
<p>　　}</p>
<p>　　else {</p>
<p>　　return “Unknown(“.$thing.”)”;</p>
<p>　　}</p>
<p>　　}</p>
<p>　　需要的时候，在程序中简单地加入下面的一条代码即可查看程序中的所使用的变量(包括数组和对象)的类型和值：</p>
<p>　　echo ss_as_string($my_variable);</p>
<p>　　使用下面的语句，我们可以直接查看程序中所有的变量的值：</p>
<p>　　echo ss_as_string($GLOBALS);</p>
<p>　　3. 控制Log信息的函数</p>
<p>　　调试PHP程序的另外一种重要的方法就是查看Log信息。如果能够方便地控制Log信息的级别以及Log信息的显示内容，将会给程序调试带来更多的便利。下面的几个函数可以方便地实现这个功能。</p>
<p>　　$ss_log_level = 0;</p>
<p>　　$ss_log_filename = /tmp/ss-log;</p>
<p>　　$ss_log_levels = array(</p>
<p>　　NONE =&gt; 0,</p>
<p>　　ERROR =&gt; 1,</p>
<p>　　INFO =&gt; 2,</p>
<p>　　DEBUG =&gt; 3);</p>
<p>　　function ss_log_set_level ($level = ERROR) {</p>
<p>　　global $ss_log_level;</p>
<p>　　$ss_log_level = $level;</p>
<p>　　}</p>
<p>　　function ss_log ($level, $message) {</p>
<p>　　global $ss_log_level, $ss-log-filename;</p>
<p>　　if ($ss_log_levels[$ss_log_level] &lt; $ss_log_levels[$level]) {</p>
<p>　　// 不显示Log信息</p>
<p>　　return false;</p>
<p>　　}</p>
<p>　　$fd = fopen($ss_log_filename, “a+”);</p>
<p>　　fputs($fd, $level. &#8211; [.ss_timestamp_pretty().] &#8211; .$message.”n”);</p>
<p>　　fclose($fd);</p>
<p>　　return true;</p>
<p>　　}</p>
<p>　　function ss_log_reset () {</p>
<p>　　global $ss_log_filename;</p>
<p>　　@unlink($ss_log_filename);</p>
<p>　　}</p>
<p>　　在上面的函数中，有四个Log级别变量。运行PHP程序时，只有当Log的级别低于预设的级别值时，Log信息才可以被记录和显示出来。例如，在程序中加入如下的一条语句：</p>
<p>　　ss_log_set_level(INFO);</p>
<p>　　那么，运行PHP程序时，只有ERROR和INFO级别的LOG信息才能被记录和显示出来，DEBUG级的信息则被忽略了。除此之外，我们还可以设定显示的信息内容，其语句如下：</p>
<p>　　ss_log(ERROR, “testing level ERROR”);</p>
<p>　　ss_log(INFO, “testing level INFO”);</p>
<p>　　ss_log(DEBUG, “testing level DEBUG”);</p>
<p>　　你也可以随时使用下面的语句清空LOG信息：</p>
<p>　　ss_log_reset();</p>
<p>　　4.速度测试函数</p>
<p>　　为了优化代码，我们需要一种可以测试代码运行时间的方法，从而来选择最优的代码。下面的函数可以测试运行代码所需的时间：</p>
<p>　　function ss_timing_start ($name = default) {</p>
<p>　　global $ss_timing_start_times;</p>
<p>　　$ss_timing_start_times[$name] = explode( , microtime());</p>
<p>　　}</p>
<p>　　function ss_timing_stop ($name = default) {</p>
<p>　　global $ss_timing_stop_times;</p>
<p>　　$ss_timing_stop_times[$name] = explode(, microtime());</p>
<p>　　}</p>
<p>　　function ss_timing_current ($name = default) {</p>
<p>　　global $ss_timing_start_times, $ss_timing_stop_times;</p>
<p>　　if (!isset($ss_timing_start_times[$name])) {</p>
<p>　　return 0;</p>
<p>　　}</p>
<p>　　if (!isset($ss_timing_stop_times[$name])) {</p>
<p>　　$stop_time = explode(, microtime());</p>
<p>　　}</p>
<p>　　else {</p>
<p>　　$stop_time = $ss_timing_stop_times[$name];</p>
<p>　　}</p>
<p>　　$current = $stop_time[1] &#8211; $ss_timing_start_times[$name][1];</p>
<p>　　$current += $stop_time[0] &#8211; $ss_timing_start_times[$name][0];</p>
<p>　　return $current;</p>
<p>　　}</p>
<p>　　现在可以轻松地检查任何一段代码的执行时间了，甚至我们可以同时使用多个计时器，只需在使用上述的几个函数时设定不同的参数作为计时器的名称就可以了。</p>
<p>　　5.调试和优化数据库的操作</p>
<p>　　对于数据库来说，运行速度是至关重要的。尽管很多书籍和文章都讲授了一些快速运行数据库的方法，但是所有的方法都必须经过实践的检验。下面我们将把 PHPLib函数库中的query()函数和上面介绍的几个函数综合起来编写成新的query()函数，和原先的函数相比，这个函数增加了运行时间的监测 功能。</p>
<p>　　function query($Query_String, $halt_on_error = 1) {</p>
<p>　　$this-&gt;connect();</p>
<p>　　ss_timing_start();</p>
<p>　　$this-&gt;Query_ID = @mysql_query($Query_String,$this-&gt;Link_ID);</p>
<p>　　ss_timing_stop();</p>
<p>　　ss_log(INFO, ss_timing_current(). Secs &#8211; .$Query_String);</p>
<p>　　$this-&gt;Row = 0;</p>
<p>　　$this-&gt;Errno = mysql_errno();</p>
<p>　　$this-&gt;Error = mysql_error();</p>
<p>　　if ($halt_on_error &amp;&amp; !$this-&gt;Query_ID) {</p>
<p>　　$this-&gt;halt(“Invalid SQL: “.$Query_String);</p>
<p>　　}</p>
<p>　　return $this-&gt;Query_ID;</p>
<p>　　}</p>
<p>　　编写漂亮的代码</p>
<p>　　1.将后台程序与前端程序分开</p>
<p>　　在编写PHP程序时，有些代码是用来处理一些事务，例如操作数据库、进行数学运算等，而另外的一些代码则只是事务处理的结果显示出来，例如一些使用 echo语句将结果以HTML的格式显示在Web浏览器上的PHP代码以及那些直接嵌入PHP程序的HTML代码。首先我们应该清晰地区分这两种代码，把 前者称为后台程序，把后者称为前端程序。</p>
<p>　　因为PHP是一种嵌入式编程语言，也就是说，所有的PHP代码都可以嵌入到HTML代码之中，这为程序的编写带来了许多便利之处。但是，“物极必反”，如果在一段较长的程序中将PHP代码和HTML代码混合编写，这将使程序杂乱无章，不利于程序的维护和阅读。</p>
<p>　　所以我们需要尽可能地将这些程序中混杂于HTML代码中的PHP代码移植出来，在专门的文件中将这些代码封装成函数，然后在HTML代码中使用include语句来包含这些文件，在适当的位置调用这些函数即可。</p>
<p>　　这种做法一方面使HTML代码和PHP代码都简单易读，另一方面因为HTML代码需要不断更新，而这种分离的方法可以确保后台程序不会被破坏。同前端 程序不同，后台程序更多追求的是稳定、结构化，极少更改，所以应该认真地设计和管理。其实，在设计台程序时，投入大量时间是值得的，“现在栽树，以后乘 凉”，在以后的设计工作中将可以轻松地使用现在编写的后台程序。</p>
<p>　　2.灵活使用包含文件</p>
<p>　　正如前面所说的那样后台程序应当安排在一系列的包含文件中。包含文件可以通过include语句在需要时动态装入，也可以在php.ini文件中通过 使用auto_prepend_file指令预先自动装入。如果使用后一种方法的话，虽然取得了一劳永逸的好处，但是也有一些缺点值得我们注意。下面的一 段代码向我们展示了解析一个庞大的包含文件需要一定的时间：</p>
<p>　　require(timing.inc);</p>
<p>　　ss_timing_start();</p>
<p>　　include(test.inc);</p>
<p>　　ss_timing_stop();</p>
<p>　　echo</p>
<p>　　.ss_timing_current().</p>
<p>　　;</p>
<p>　　?&gt;</p>
<p>　　在上面的代码中，test.inc是一个1000行的包含文件，运行的结果显示，解析这个包含文件花费了0.6秒钟，对于一个大型网站来说，这个速度 并不是可以忽略不记的。使用包含文件的另外一个缺点是：如果一个文件中的一个语句发生错误，将会使整个网站的PHP程序都无法运行。所以使用起来也及其小 心。其实，对包含文件稍做处理，即可以使包含文件只在需要时进行解析。下面的代码使abc.inc文件只在程序需要时才作解析：</p>
<p>　　if ( defined( __LIBA_INC) ) return; define( __LIBA_INC, 1 ); /* * 代码&#8230; */ ?&gt;</p>
<p>　　3.使用面向对象的编程方法</p>
<p>　　PHP也是一种面向对象的语言，面向对象的编程方法是优秀的程序员们非常推崇的一种软件设计方法，在PHP编程中可以充分发挥面向对象语言的优势，对 编程中的对象进行封装。在前面的代码中，我们使用了面向对象的方法，例如在管理数据库时，我们将query()函数封装进数据库类中，这极大地方便了代码 的管理，增加了程序的可读性。</p>
<p>　　追求程序速度，而不是编程的速度</p>
<p>　　在网站建设中，程序运行速度和网页下载速度都是关系成败的重要因素。作为一名Web程序员，应该更加注意代码的运行速度。下面介绍的几种方法都在不同程度上提高了代码的运行速度。</p>
<p>　　1.使用内嵌的HTML代码，而不是PHP的echo语句。</p>
<p>　　因为PHP是一门嵌入式Web编程语言，可以将HTML代码和PHP代码相互嵌入。但是很多程序员担心在HTML代码中过多的使用&#8221;"嵌入PHP代码 会多次调用PHP解释器，从而降低了PHP代码的运行速度，所以宁愿使用PHP的echo语句来输出HTML代码，而不直接使用HTML代码。</p>
<p>　　但事实却恰恰相反。每一个PHP页面只调用一次PHP解释器来解释所有的PHP代码，所以，只在需要时才嵌入PHP代码，而大多数的时候直接使用 HTML代码输入结果，不但不会降低程序的运行速度，而且因为减少了对echo语句的解析，往往可以提高代码的运行速度。下面的一段代码证明了我们的结 论。在这段代码中，我们使用了前面介绍的时间测试函数。</p>
<p>　　2.使用str-replace而不是ereg-replace</p>
<p>　　习惯使用Perl进行编程的程序员更加愿意使用ereg_replace完成字符串替换工作，因为在PHP中ereg_replace的用法和 Perl中模式匹配的用法相近。但是，下面的这段代码证明，使用str_replace 代替 ereg_replace将可以大大提高代码的运行速度。测试str_replace和ereg_replace的运行速度：</p>
<p>　　//这段代码测试str_replace的运行速度 emphasis; ?&gt;</p>
<p>　　for ($i=0; $i&lt;1000; $i++) {</p>
<p>　　str_replace(i&gt;, b&gt;, $string).</p>
<p>　　;</p>
<p>　　}</p>
<p>　　?&gt;</p>
<p>　　//这段代码测试ereg_replace的运行速度</p>
<p>　　for ($i=0; $i&lt;1000; $i++) {</p>
<p>　　ereg_replace(&lt;([/]*)i&gt;, &lt;<a href="file://1b/">\\1b</a>&gt;, $string).</p>
<p>　　;</p>
<p>　　}</p>
<p>　　?&gt;</p>
<p>　　3.注意字符串的引用</p>
<p>　　PHP和其它很多编程语言一样，可以使用双引号(\&#8221;\&#8221;)来引用字符串，也可以使用单引号()。但是在PHP中，如果使用双引号来引用字符串，那么 PHP解析器将首先分析字符串中有没有对变量的引用，有变量的话，将对变量进行替换。如果是单引号，则没有如此复杂——直接将单引号包含起来的所有字符串 直接显示出来。显然，在PHP编程中，如果使用单引号引用字符串变量要比使用双引号快速一些。</p>
<p>　　4.在数据库中避免使用联合操作</p>
<p>　　比起其它的Web编程语言来说，PHP的数据库功能十分强大。但是在PHP中数据库的运行仍然是一件十分费时费力的事情，所以，作为一个Web程序员，要尽量减少数据库的查询操作，同时应该为数据库建立适当的索引。</p>
<p>　　另一件值得注意的事情是在用PHP操作数据库时，尽可能不使用多个数据表的联合操作，尽管联合操作可以增强数据库的查询功能，但是却大大增加了服务器的负担。为了说明这个问题，我们可以看看下面的这个简单的例子。</p>
<p>　　我们在数据库中创建了两个数据表foo和big_foo。在数据表foo中，只有一个字段，包含了从1-1000之间的所有自然数。数据表 big_foo同样只有一个字段，但包含了从1-1,000,000之间的全部自然数。所以，从大小上说，big_foo等于foo与它自身进行了联合操 作。</p>
<p>　　$db-&gt;query(\&#8221;select * from foo\&#8221;);</p>
<p>　　0.032273 secs</p>
<p>　　$db-&gt;next_record();</p>
<p>　　0.00048999999999999 secs</p>
<p>　　$db-&gt;query(\&#8221;insert into foo values (NULL)\&#8221;);</p>
<p>　　0.019506 secs</p>
<p>　　$db-&gt;query(\&#8221;select * from foo as a, foo as b\&#8221;);</p>
<p>　　17.280596 secs</p>
<p>　　$db-&gt;query(\&#8221;select * from foo as a, foo as b where a.id &gt; b.id\&#8221;);</p>
<p>　　14.645251 secs</p>
<p>　　$db-&gt;query(\&#8221;select * from foo as a, foo as b where a.id = b.id\&#8221;);</p>
<p>　　0.041269 secs</p>
<p>　　$db-&gt;query(\&#8221;select * from big_foo\&#8221;);</p>
<p>　　25.393672 secs</p>
<p>　　从上面操作结果我们可以发现，对于两个有1000条记录的数据表进行联合，其速度并不比对一个1000000条纪录的大型数据表单独进行操作快多少。</p>
<p>　　5.注意include与require的区别</p>
<p>　　在PHP变成中，include()与require()的功能相同，但在用法上却有一些不同，include()是有条件包含函数，而 require()则是无条件包含函数。例如在下面的一个例子中，如果变量$somgthing为真，则将包含文件somefile：</p>
<p>　　if($something){ include(\&#8221;somefile\&#8221;); }</p>
<p>　　但不管$something取何值，下面的代码将把文件somefile包含进文件里：</p>
<p>　　if($something){ require(\&#8221;somefile\&#8221;); }</p>
<p>　　下面的这个有趣的例子充分说明了这两个函数之间的不同。</p>
<p>　　$i = 1; while ($i &lt; 3) { require(\&#8221;somefile.$i\&#8221;); $i++; }</p>
<p>　　在这段代码中，每一次循环的时候，程序都将把同一个文件包含进去。很显然这不是程序员的初衷，从代码中我们可以看出这段代码希望在每次循环时，将不同的文件包含进来。如果要完成这个功能，必须求助函数include();</p>
<p>　　$i = 1; while ($i &lt; 3) { include(\&#8221;somefile.$i\&#8221;); $i++; }</p>
<p>　　6.注意echo和print的区别</p>
<p>　　PHP中echo和print的功能也基本相同，但是两者之间也有细微差别。在PHP代码中可以把print作为一个普通函数来使用，例如执行下面的代码后变量$res的值将为1。</p>
<p>　　$ret = print \&#8221;Hello World\&#8221;;</p>
<p>　　这意味着print可用在一些复杂的表达式中，而echo则不行。同样，在代码中echo语句的运行速度要略微快于print语句，因为echo语句不要求返回任何数值。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/460/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Navicat for MySQL 8 注册码</title>
		<link>http://blog.nmi.cn/archives/458</link>
		<comments>http://blog.nmi.cn/archives/458#comments</comments>
		<pubDate>Sat, 24 Dec 2011 05:31:55 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://blog.pany.net.cn/archives/458</guid>
		<description><![CDATA[强大的mysql数据库管理软件Navicat for MySQL 8 注册码
姓名(Name)：3ddown.com
组织(Organization)：3ddown.com
注册码(Serial)：NAVJ-W56S-3YUU-MVHV
]]></description>
			<content:encoded><![CDATA[<p>强大的mysql数据库管理软件Navicat for MySQL 8 注册码</p>
<p>姓名(Name)：3ddown.com<br />
组织(Organization)：3ddown.com<br />
注册码(Serial)：NAVJ-W56S-3YUU-MVHV</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/458/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>php开发效率提高的方法</title>
		<link>http://blog.nmi.cn/archives/455</link>
		<comments>http://blog.nmi.cn/archives/455#comments</comments>
		<pubDate>Sat, 26 Nov 2011 04:42:37 +0000</pubDate>
		<dc:creator>pany.net.cn</dc:creator>
				<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.pany.net.cn/?p=455</guid>
		<description><![CDATA[就其本质而言，如果你掌握了以PHP语言“做事”的方式，那么在使用它时就会得心应手，因此值得你去投入精力去了解这些方式。在PHP中，单纯按照自己思路去解决问题往往会是一种错误的办法。这并不是因为你是一个糟糕的程序员，而是因为如果你想写出好的可维护性强的代码，有些标准技巧是你必须要使用的。下面让我们一起看一下你需要知道的10大技巧。
1、如何正确的创建一个网站的Index页面
　　创建每一个网站时，建立网站的index页面是首要做的事情之一。如果你是一个PHP新手，在编写index页面时典型的做法是只对index页面所需的内容进行编程，其它链接创建另一个页面。不过，如果想学习一种更高效的方式来实现PHP编程，可以采用“index.php?page=home”模式，许多网站都在采用这种模式。
2、使用Request Global Array抓取数据
　　实际上我们没有任何理由使用$_GET和$_POST数组来抓取数值。$_REQUEST这个全局数组能够让你获取一个get或form请求。因此，多数情况下解析数据的更高效代码大体如下：
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 0;  3、利用var_dump进行PHP代码调试
　　如果你在寻找php调试技术，我必须说var_dump应该是你要找的目标。在显示php信息方面这个命令可以满足你的所有需要。而调试代码的多数情况与得到PHP中的数值有关。
4、PHP处理代码逻辑，Smarty处理展现层
　　Smarty是一个使用PHP写出来的模板PHP模板引擎，是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容，提供了一种易于管理和使用的方法，用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲，目的就是要使PHP程序员同前端人员分离，使程序员改变程序的逻辑内容不会影响到前端人员的页面设计，前端人员重新修改页面不会影响到程序的程序逻辑，这在多人合作的项目中显的尤为重要。
5、的确需要使用全局数值时，创建一个Config文件
　　动辄创建全局数值是一种糟糕的做法，不过有时候实际情况的确又需要这么做。对于数据库表或数据库连接信息使用全局数值是一个不错的想法，但不要在你的PHP代码中频繁使用全局数值。另外，更好的一种做法是把你的全局变量存放在一个config.php文件中。
6、如果未定义，禁止访问！
　　如果你正确的创建了页面，那么任何其他人没有理由访问index.php或home.php之外的index.php页面。一旦index.php被访问后，你可以通过获得变量的方式来打开需要的页面。你的index页面应该包含类似的以下代码：
define(‘yourPage’,1); 　　然后，其它页面应该包含：
if (!defined(‘yourPage’)) die(‘Access Denied’); 　　这么做的目的是防止直接访问你的其它php页面。这样，任何试图不通过index.php访问其它网页的人，将得到“访问被拒绝”的消息。
7、创建一个数据库类
　　如果你正在进行数据库编程（在PHP中非常常见的任务），一个不错的想法是创建一个数据库类来处理任何数据库管理功能。示例代码如下：
public function dbExec($query)      {          $result = $this-&#62;db-&#62;exec($query);          if (PEAR::isError($result))              errorRedirect($result-&#62;getMessage(), true);          else             return $result;      }  　　这个函数仅接收一个查询语句并对其执行。它还处理可能出现的任何错误。你还可以在这儿包含审核代码，不过我更喜欢使用一个类似的审核函数：
// checks if arguments given are integer values not less than 0 – has multiple arguments      function sanitizeInput()      {          $numargs = func_num_args();          $arg_list = func_get_args();          for [...]]]></description>
			<content:encoded><![CDATA[<p>就其本质而言，如果你掌握了以PHP语言“做事”的方式，那么在使用它时就会得心应手，因此值得你去投入精力去了解这些方式。在PHP中，单纯按照自己思路去解决问题往往会是一种错误的办法。这并不是因为你是一个糟糕的程序员，而是因为如果你想写出好的可维护性强的代码，有些标准技巧是你必须要使用的。下面让我们一起看一下你需要知道的10大技巧。</p>
<p>1、如何正确的创建一个网站的Index页面</p>
<p>　　创建每一个网站时，建立网站的index页面是首要做的事情之一。如果你是一个PHP新手，在编写index页面时典型的做法是只对index页面所需的内容进行编程，其它链接创建另一个页面。不过，如果想学习一种更高效的方式来实现PHP编程，可以采用“index.php?page=home”模式，许多网站都在采用这种模式。</p>
<p>2、使用Request Global Array抓取数据</p>
<p>　　实际上我们没有任何理由使用$_GET和$_POST数组来抓取数值。$_REQUEST这个全局数组能够让你获取一个get或form请求。因此，多数情况下解析数据的更高效代码大体如下：</p>
<p>$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 0;  3、利用var_dump进行<a title="php代码" href="http://www.phpboke.com/">PHP代码</a>调试</p>
<p>　　如果你在寻找php调试技术，我必须说var_dump应该是你要找的目标。在显示php信息方面这个命令可以满足你的所有需要。而调试代码的多数情况与得到PHP中的数值有关。</p>
<p>4、PHP处理代码逻辑，Smarty处理展现层</p>
<p>　　Smarty是一个使用PHP写出来的模板PHP模板引擎，是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容，提供了一种易于管理和使用的方法，用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲，目的就是要使PHP程序员同前端人员分离，使程序员改变程序的逻辑内容不会影响到前端人员的页面设计，前端人员重新修改页面不会影响到程序的程序逻辑，这在多人合作的项目中显的尤为重要。</p>
<p>5、的确需要使用全局数值时，创建一个Config文件</p>
<p>　　动辄创建全局数值是一种糟糕的做法，不过有时候实际情况的确又需要这么做。对于数据库表或数据库连接信息使用全局数值是一个不错的想法，但不要在你的PHP代码中频繁使用全局数值。另外，更好的一种做法是把你的全局变量存放在一个config.php文件中。</p>
<p>6、如果未定义，禁止访问！</p>
<p>　　如果你正确的创建了页面，那么任何其他人没有理由访问index.php或home.php之外的index.php页面。一旦index.php被访问后，你可以通过获得变量的方式来打开需要的页面。你的index页面应该包含类似的以下代码：</p>
<p>define(‘yourPage’,1); 　　然后，其它页面应该包含：</p>
<p>if (!defined(‘yourPage’)) die(‘Access Denied’); 　　这么做的目的是防止直接访问你的其它php页面。这样，任何试图不通过index.php访问其它网页的人，将得到“访问被拒绝”的消息。</p>
<p>7、创建一个数据库类</p>
<p>　　如果你正在进行数据库编程（在PHP中非常常见的任务），一个不错的想法是创建一个数据库类来处理任何数据库管理功能。示例代码如下：</p>
<p>public function dbExec($query)      {          $result = $this-&gt;db-&gt;exec($query);          if (PEAR::isError($result))              errorRedirect($result-&gt;getMessage(), true);          else             return $result;      }  　　这个函数仅接收一个查询语句并对其执行。它还处理可能出现的任何错误。你还可以在这儿包含审核代码，不过我更喜欢使用一个类似的审核函数：</p>
<p>// checks if arguments given are integer values not less than 0 – has multiple arguments      function sanitizeInput()      {          $numargs = func_num_args();          $arg_list = func_get_args();          for ($i = 0; $i &lt; $numargs; $i++) {              if (!is_numeric($arg_list[$i]) || $arg_list[$i] &lt; 0)                  errorRedirect(“Unexpected variable value”, true);          }      }  8、一个php文件处理输入，一个class.php文件处理具体功能</p>
<p>　　不让代码变得混乱的一个重要方法是：获取用户输入后，将其重定向到其它函数来进行处理。原理非常简单，<a title="php" href="http://www.phpboke.com/">php</a>文件获得我们需要的任何输入，然后将其执行重定向到类文件中的一个函数。举例来讲，假设有一个类似“index.php?page=profile&amp;action=display”的URL。由profile.php来检索该网址并得到操作是“display”。然后使用一个简单的switch函数，我们来执行真正的显示函数：</p>
<p>require_once PROJECTROOT.’libs/messages.class.php’;      $message = new Message();      switch ($action)    {        case ‘display’:            $message-&gt;display();            break;      … 　　如上所示，我使用了一个消息类，然后开始进行switch检查。$message只是被类中的调用函数使用的一个对象。</p>
<p>9、了解你的SQL语句，并总是对其审查（Sanitize）</p>
<p>　　正如我以前所提到的，任何php网站中最重要的部分有99%的可能是数据库。因此，你需要非常熟悉如何正确的使用sql。学会关联表和更多高级技术。下面我将展示一个使用MySQL的函数示例，并使用本文第7条函数进行审查。</p>
<p>private function getSentMessages($id)      {     $this-&gt;util-&gt;sanitizeInput($id);         $pm_table = $GLOBALS['config']['privateMsg'];      $users = $GLOBALS['config']['users'];          $sql = “SELECT PM.*, USR.username as name_sender FROM $pm_table PM, $users USR              WHERE id_sender = ‘$id’ AND sender_purge = FALSE AND USR.id = PM.id_receiver AND is_read = TRUE              ORDER BY date_sent DESC”;      $result = $this-&gt;dbQueryAll($sql);         return $result;      }  　　首先，我们对用户输入进行检查（通过一个GET变量传递消息id），然后我们执行我们的SQL命令。注意这儿SQL的用法。你需要了解如何使用别名和关联表。</p>
<p>10、当你只需要一个对象时，使用单例模式</p>
<p>　　在PHP中相当常见的一种情形时，我们只需要创建一个对象一次，然后在我们的整个程序中使用它。一个很好的例子就是smarty变量，一旦被初始化后就可以在任何地方使用。这种情形的一个很好实现方案就是单例模式。示例代码如下：</p>
<p>function smartyObject()      {          if ($GLOBALS['config']['SmartyObj'] == 0)          {              $smarty = new SmartyGame();              $GLOBALS['config']['SmartyObj'] = $smarty;          }          else             $smarty = $GLOBALS['config']['SmartyObj'];          return $smarty;      }  　　注意，我们拥有一个全局smarty变量（该示例中它在config.php中被初始化），如果它的值为0，我们将创建一个新smarty对象。否则，它意味着该对象已经被创建，我们只需要返回它。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.nmi.cn/archives/455/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

