PHP里的尾递归及其优化

不同的语言对尾递归的支持都有所不同,编译器的优化也不尽相同。我们之前看了C语言的尾递归,那么在PHP里又是如何的呢?

PHP对尾递归没有优化效果

先来看下实验。 [php] <?php function factorial($n) { if($n == 0) { return 1; } return factorial($n-1) * $n; } var_dump(factorial(100)); ?> [/php] 如果安装了XDebug的话,可能会遇到如下错误: Fatal error: Maximum function nesting level of '100' reached, aborting! 这是XDebug的一个保护机制,可以通过max_nesting_level选项来设置。放开设置的话,程序还是能够正常运行的。 即便代码能正常运行,只要我们不断增大参数,程序迟早会报错: Fatal error:  Allowed memory size of … bytes exhausted 为什么呢?简单点说就是递归造成了栈溢出。按照之前的思路,我们可以试下用尾递归来消除递归对栈的影响,提高程序的效率。 [php] <?php function factorial($n, $acc) { if($n == 0) { return $acc; } return factorial($n-1, $acc * $n); } var_dump(factorial(100, 1)); ?> [/php] XDebug同样报错,并且程序的执行时间并没有明显变化。 Fatal error: Maximum function nesting level of '100' reached, aborting! 事实证明,尾递归在php中是没有任何优化效果的。

PHP如何消除递归

先看看下面的源代码: [php] <?php function factorial($n, $accumulator = 1) { if ($n == 0) { return $accumulator; } return function() use($n, $accumulator) { return factorial($n - 1, $accumulator * $n); }; } function trampoline($callback, $params) { $result = call_user_func_array($callback, $params); while (is_callable($result)) { $result = $result(); } return $result; } var_dump(trampoline('factorial', array(100))); ?> [/php] 现在XDebug不再警报效率问题了。 注意到trampoline()函数没?简单点说就是利用高阶函数消除递归。想更进一步了解 call_user_func_array,可以参看这篇文章:PHP函数补完:call_user_func()与call_user_func_array() 还有很多别的方法可以用来规避递归引起的栈溢出问题,比如说Python中可以通过装饰器和异常来消灭尾调用,让人有一种别有洞天的感觉。

小结

在C中的尾递归优化是gcc编译器做的。一般的线性递归修改成为尾递归最大的优势在于减少了递归调用栈的开销。从php那个例子就明显看出来递归开销对程序的影响。但是并不是所有语言都支持尾递归的,即使支持尾递归的语言也一般是在编译阶段对尾递归进行优化,比如C语言对尾递归的优化。在使用尾递归对代码进行优化的时候,必须先了解这门语言对尾递归的支持。 在PHP里,除非能提升代码可读性,否则没有必要使用递归;迫不得已之时,最好考虑使用Tail Call或Trampoline等技术来规避潜在的栈溢出问题。 原文地址 http://www.nowamagic.net/librarys/veda/detail/2334

linux下关于mySQL的安装和配置

 
linux下关于mySQL的安装和配置
这篇博文很经典!推荐给大家!
一、引言 想使用Linux已经很长时间了,由于没有硬性任务一直也没有系统学习,近日由于工作需要必须使用Linux下的MySQL。本以为有Windows下使用SQL Server的经验,觉得在
Linux下安装MySql应该是易如反掌的事,可在真正安装和使用MySQL时走了很多弯路,遇见很多问题,毕竟Linux 和Windows本身就有很大区别。为了让和我一样的初学者在学习的
过程中少走弯路,尽快入门,写了此文,希望对您有所帮助。本文的Linux环境是 Red Hat 9.0,MySQL是4.0.16。
二、安装Mysql 1、下载MySQL的安装文件 安装MySQL需要下面两个文件: MySQL-server-4.0.16-0.i386.rpm MySQL-client-4.0.16-0.i386.rpm 下载地址为:http://www.mysql.com/downloads/mysql-4.0.html,打开此网页,下拉网页找到“Linux x86 RPM downloads”项,找到“Server”和“Client programs”项
,下载需要的上述两个rpm文件。
   2、安装MySQL rpm文件是Red Hat公司开发的软件安装包,rpm可让Linux在安装软件包时免除许多复杂的手续。该命令在安装时常用的参数是 –ivh ,其中i表示将安装指定的rmp软件包,V
表示安装时的详细信息,h表示在安装期间出现“#”符号来显示目前的安装过程。这个符号将持续到安装完成后才停止。 1)安装服务器端 在有两个rmp文件的目录下运行如下命令: [root@test1 local]# rpm -ivh MySQL-server-4.0.16-0.i386.rpm 显示如下信息。 warning: MySQL-server-4.0.16-0.i386.rpm: V3 DSA signature: NOKEY, key ID 5072e1f5 Preparing...       ########################################### [100%] 1:MySQL-server     ########################################### [100%] 。。。。。。(省略显示) /usr/bin/mysqladmin -u root password 'new-password' /usr/bin/mysqladmin -u root -h test1 password 'new-password' 。。。。。。(省略显示) Starting mysqld daemon with databases from /var/lib/mysql 如出现如上信息,服务端安装完毕。测试是否成功可运行netstat看Mysql端口是否打开,如打开表示服务已经启动,安装成功。Mysql默认的端口是3306。 [root@test1 local]# netstat -nat Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address      Foreign Address     State tcp  0  0 0.0.0.0:3306     0.0.0.0:*      LISTEN 上面显示可以看出MySQL服务已经启动。 2)安装客户端 运行如下命令: [root@test1 local]# rpm -ivh MySQL-client-4.0.16-0.i386.rpm warning: MySQL-client-4.0.16-0.i386.rpm: V3 DSA signature: NOKEY, key ID 5072e1f5 Preparing...    ########################################### [100%] 1:MySQL-client  ########################################### [100%] 显示安装完毕。 用下面的命令连接mysql,测试是否成功。
三、登录MySQL
   登录MySQL的命令是mysql, mysql 的使用语法如下: mysql [-u username] [-h host] [-p[password]] [dbname] username 与 password 分别是 MySQL 的用户名与密码,mysql的初始管理帐号是root,没有密码,注意:这个root用户不是Linux的系统用户。MySQL默认用户是root,由于
初始没有密码,第一次进时只需键入mysql即可。 [root@test1 local]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 4.0.16-standard Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> 出现了“mysql>”提示符,恭喜你,安装成功! 增加了密码后的登录格式如下: mysql -u root -p Enter password: (输入密码) 其中-u后跟的是用户名,-p要求输入密码,回车后在输入密码处输入密码。
   注意:这个mysql文件在/usr/bin目录下,与后面讲的启动文件/etc/init.d/mysql不是一个文件。
四、MySQL的几个重要目录
   MySQL安装完成后不象SQL Server默认安装在一个目录,它的数据库文件、配置文件和命令文件分别在不同的目录,了解这些目录非常重要,尤其对于Linux的初学者,因为
Linux本身的目录结构就比较复杂,如果搞不清楚MySQL的安装目录那就无从谈起深入学习。
   下面就介绍一下这几个目录。
   1、数据库目录 /var/lib/mysql/
   2、配置文件 /usr/share/mysql(mysql.server命令及配置文件)
   3、相关命令 /usr/bin(mysqladmin mysqldump等命令)
   4、启动脚本 /etc/rc.d/init.d/(启动脚本文件mysql的目录)
五、修改登录密码
   MySQL默认没有密码,安装完毕增加密码的重要性是不言而喻的。 1、命令 usr/bin/mysqladmin -u root password 'new-password' 格式:mysqladmin -u用户名 -p旧密码 password 新密码 2、例子 例1:给root加个密码123456。 键入以下命令 : [root@test1 local]# /usr/bin/mysqladmin -u root password 123456 注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。
3、测试是否修改成功 1)不用密码登录 [root@test1 local]# mysql ERROR 1045: Access denied for user: 'root@localhost' (Using password: NO) 显示错误,说明密码已经修改。 2)用修改后的密码登录 [root@test1 local]# mysql -u root -p Enter password: (输入修改后的密码123456) Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4 to server version: 4.0.16-standard Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> 成功! 这是通过mysqladmin命令修改口令,也可通过修改库来更改口令。
六、启动与停止
   1、启动 MySQL安装完成后启动文件mysql在/etc/init.d目录下,在需要启动时运行下面命令即可。 [root@test1 init.d]# /etc/init.d/mysql start
   2、停止 /usr/bin/mysqladmin -u root -p shutdown
   3、自动启动 1)察看mysql是否在自动启动列表中 [root@test1 local]# /sbin/chkconfig –list 2)把MySQL添加到你系统的启动服务组里面去 [root@test1 local]# /sbin/chkconfig – add mysql 3)把MySQL从启动服务组里面删除。 [root@test1 local]# /sbin/chkconfig – del mysql 七、更改MySQL目录
   MySQL默认的数据文件存储目录为/var/lib/mysql。假如要把目录移到/home/data下需要进行下面几步:
   1、home目录下建立data目录 cd /home mkdir data
   2、把MySQL服务进程停掉: mysqladmin -u root -p shutdown
   3、把/var/lib/mysql整个目录移到/home/data mv /var/lib/mysql /home/data/ 这样就把MySQL的数据文件移动到了/home/data/mysql下
   4、找到my.cnf配置文件 如果/etc/目录下没有my.cnf配置文件,请到/usr/share/mysql/下找到*.cnf文件,拷贝其中一个到/etc/并改名为my.cnf)中。命令如下: [root@test1 mysql]# cp /usr/share/mysql/my-medium.cnf /etc/my.cnf
   5、编辑MySQL的配置文件/etc/my.cnf 为保证MySQL能够正常工作,需要指明mysql.sock文件的产生位置。 修改socket=/var/lib/mysql/mysql.sock一行中等号右边的值为:/home/mysql/mysql.sock 。操作如下
: vi  my.cnf    (用vi工具编辑my.cnf文件,找到下列数据修改之) # The MySQL server [mysqld] port   = 3306 #socket  = /var/lib/mysql/mysql.sock(原内容,为了更稳妥用“#”注释此行) socket  = /home/data/mysql/mysql.sock   (加上此行)
   6、修改MySQL启动脚本/etc/rc.d/init.d/mysql 最后,需要修改MySQL启动脚本/etc/rc.d/init.d/mysql,把其中datadir=/var/lib/mysql一行中,等号右边的路径改成你现在的实际存放路径:home/data/mysql。 [root@test1 etc]# vi /etc/rc.d/init.d/mysql #datadir=/var/lib/mysql    (注释此行) datadir=/home/data/mysql   (加上此行)
   7、重新启动MySQL服务 /etc/rc.d/init.d/mysql start 或用reboot命令重启Linux 如果工作正常移动就成功了,否则对照前面的7步再检查一下。 八、MySQL的常用操作
   注意:MySQL中每个命令后都要以分号;结尾。
   1、显示数据库 mysql> show databases; +----------+ | Database | +----------+ | mysql  | | test   | +----------+ 2 rows in set (0.04 sec) Mysql刚安装完有两个数据库:mysql和test。mysql库非常重要,它里面有MySQL的系统信息,我们改密码和新增用户,实际上就是用这个库中的相关表进行操作。
   2、显示数据库中的表 mysql> use mysql; (打开库,对每个库进行操作就要打开此库,类似于foxpro ) Database changed
   mysql> show tables; +-----------------+ | Tables_in_mysql | +-----------------+ | columns_priv  | | db       | | func      | | host      | | tables_priv   | | user      | +-----------------+ 6 rows in set (0.01 sec)
   3、显示数据表的结构: describe 表名;
   4、显示表中的记录: select * from 表名; 例如:显示mysql库中user表中的纪录。所有能对MySQL用户操作的用户都在此表中。 Select * from user;
   5、建库: create database 库名; 例如:创建一个名字位aaa的库 mysql> create databases aaa; 6、建表: use 库名; create table 表名 (字段设定列表); 例如:在刚创建的aaa库中建立表name,表中有id(序号,自动增长),xm(姓名),xb(性别),csny(出身年月)四个字段 use aaa; mysql> create table name (id int(3) auto_increment not null primary key, xm char(,xb char(2),csny date); 可以用describe命令察看刚建立的表结构。 mysql> describe name;
   +-------+---------+------+-----+---------+----------------+ | Field | Type  | Null | Key | Default | Extra     | +-------+---------+------+-----+---------+----------------+ | id  | int(3) |   | PRI | NULL  | auto_increment | | xm  | char( | YES |   | NULL  |        | | xb  | char(2) | YES |   | NULL  |        | | csny | date  | YES |   | NULL  |        | +-------+---------+------+-----+---------+----------------+
   7、增加记录 例如:增加几条相关纪录。 mysql> insert into name values('','张三','男','1971-10-01'); mysql> insert into name values('','白云','女','1972-05-20'); 可用select命令来验证结果。 mysql> select * from name; +----+------+------+------------+ | id | xm  | xb  | csny    | +----+------+------+------------+ | 1 | 张三 | 男  | 1971-10-01 | | 2 | 白云 | 女  | 1972-05-20 | +----+------+------+------------+
   8、修改纪录 例如:将张三的出生年月改为1971-01-10 mysql> update name set csny='1971-01-10' where xm='张三';
   9、删除纪录 例如:删除张三的纪录。 mysql> delete from name where xm='张三';
   10、删库和删表 drop database 库名; drop table 表名;
九、增加MySQL用户
   格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码" 例1、增加一个用户user_1密码为123,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入MySQL,然后键入以下命令:
   mysql> grant select,insert,update,delete on *.* to user_1@"%" Identified by "123"; 例1增加的用户是十分危险的,如果知道了user_1的密码,那么他就可以在网上的任何一台电脑上登录你的MySQL数据库并对你的数据为所欲为了,解决办法见例2。
  例2、增加一个用户user_2密码为123,让此用户只可以在localhost上登录,并可以对数据库aaa进行查询、插入、修改、删除的操作(localhost指本地主机,即MySQL数据库所
在的那台主机),这样用户即使用知道user_2的密码,他也无法从网上直接访问数据库,只能通过 MYSQL主机来操作aaa库。
   mysql>grant select,insert,update,delete on aaa.* to user_2@localhost identified by "123";
   用新增的用户如果登录不了MySQL,在登录时用如下命令:
   mysql -u user_1 -p -h 192.168.113.50 (-h后跟的是要登录主机的ip地址)
十、备份与恢复
   1、备份
   例如:将上例创建的aaa库备份到文件back_aaa中
   [root@test1 root]# cd /home/data/mysql (进入到库目录,本例库已由val/lib/mysql转到/home/data/mysql,见上述第七部分内容) [root@test1 mysql]# mysqldump -u root -p --opt aaa > back_aaa
   2、恢复
   [root@test mysql]# mysql -u root -p ccc < back_aaa

apache的配置优化

【APACHE的工作方式】 prefork模式(默认) 这个多路处理模块(MPM)实现了一个非线程型的、预派生的web服务器,它的工作方式类似于Apache 1.3。它适合于没有线程安全库,需要避免线程兼容性问题的系统。它是要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求。 这个MPM具有很强的自我调节能力,只需要很少的配置指令调整。最重要的是将MaxClients设置为一个足够大的数值以处理潜在的请求高峰,同时又不能太大,以致需要使用的内存超出物理内存的大小。 worker模式 此多路处理模块(MPM)使网络服务器支持混合的多线程多进程。由于使用线程来处理请求,所以可以处理海量请求,而系统资源的开销小于基于进程的MPM。但是,它也使用了多进程,每个进程又有多个线程,以获得基于进程的MPM的稳定性。 【apache配置参数备注】 1、KeepAlive On/Off KeepAlive指的是保持连接活跃,类似于Mysql的永久连接。换一句话说,如果将KeepAlive设置为On,那么来自同一客户端的请求就不 需要再一次连接,避免每次请求都要新建一个连接而加重服务器的负担。一般情况下,图片较多的网站应该把KeepAlive设为On。 2、KeepAliveTimeOut number 如果第二次请求和第一次请求之间超过KeepAliveTimeOut的时间的话,第一次连接就会中断,再新建第二个连接。它的设置一般考虑图片或者JS等文件两次请求间隔,我的设置经验为3-5秒。 3、MaxKeepAliveRequests 100 一次连接可以进行的HTTP请求的最大请求次数。将其值设为0将支持在一次连接内进行无限次的传输请求。事实上没有客户程序在一次连接中请求太多的页面,通常达不到这个上限就完成连接了。 4、StartServers        10 设置服务器启动时建立的子进程数量。因为子进程数量动态的取决于负载的轻重,所有一般没有必要调整这个参数。 5、MinSpareServers     10 设置空闲子进程的最小数量。所谓空闲子进程是指没有正在处理请求的子进程。如果当前 空闲子进程数少于MinSpareServers ,那么Apache将以最大每秒一个的速度产生新的子进程。只有在非常繁忙机器上才需要调整这个参数。将此参数设的太大通常是一个坏主意。 6、MaxSpareThreads     75 设置空闲子进程的最大数量。如果当前有超过MaxSpareServers数量的空 闲子进程,那么父进程将杀死多余的子进程。只有在非常繁忙机器上才需要调整这个参数。将此参数设的太大通常是一个坏主意。如果你将该指令的值设置为比 MinSpareServers小,Apache将会自动将其修改成”MinSpareServers+1″。 7、ServerLimit       2000 服务器允许配置的进程数上限。只有在你需要将MaxClients设置成高于默认值256的时候才需要使用。要将此指令的值保持和MaxClients一样。修改此指令的值必须完全停止服务后再启动才能生效,以restart方式重启动将不会生效。 8、MaxClients        256 用于伺服 客户端请求的最大请求数量(最大子进程数),任何超过MaxClients限制的请求都将进入等候队列。默认值是256,如果要提高这个值必须同时提高 ServerLimit的值。笔者建议将初始值设为(以Mb为单位的最大物理内存/2),然后根据负载情况进行动态调整。比如一台4G内存的机器,那么初 始值就是4000/2=2000。 9、MaxRequestsPerChild  0 apache.exe进程包括一个是父进程、一个是子进程,父进程接到访问请求后,将请求交由子进程处理。MaxRequestsPerChild这个指 令设定一个独立的子进程将能处理的请求数量。在处理“MaxRequestsPerChild 数字”个请求之后,子进程将会被父进程终止,这时候子进程占用的内存就会释放,如果再有访问请求,父进程会重新产生子进程进行处理。  如果 MaxRequestsPerChild缺省设为0(无限)或较大的数字(例如10000以上)可以使每个子进程处理更多的请求,不会因为不断终止、启动 子进程降低访问效率,但MaxRequestsPerChild设置为0时,如果占用了200~300M内存,即使负载下来时占用的内存也不会减少。内存 较大的服务器可以设置为0或较大的数字。内存较小的服务器不妨设置成30、50、100,以防内存溢出。所以一般情况下,如果你发现服务器的内存直线上升,建议修改该参数试试。 【apache的Rewrite】 1、是否支持使用.htaccess文件来定义或者修改apache的设置,是否支持目录列表
<Directory /> Options indexes FollowSymLinks AllowOverride All </Directory>
2、rewrite 配置 RewriteEngine on RewriteCond $1 !^(index\.php|images|robots\.txt) #定义重写发生的条件 RewriteRule ^(.*)$ /index.php/$1 [L] RewriteLog D:/lib/rewrite.log #设置rewrite日志文件,主要用来rewrite调试 RewriteLogLevel 3 #设置rewrite日志文件记录的等级,主要用来rewrite调试
  【apache的Gzip功能】 gzip可以级大的加速网站.有时压缩比率高到80%,近来测试了一下,最少都有40%以上,还是相当不错的.在Apache2之后的版本,模块名不叫gzip,而叫mod_deflate
如果要开启gzip的话,一定要打开下面二个模块. LoadModule headers_module modules/mod_headers.so LoadModule deflate_module modules/mod_deflate.so 设置压缩比率,取值范围在 1(最低) 到 9(最高)之间,不建议设置太高,虽然有很高的压缩率,但是占用更多的CPU资源. DeflateCompressionLevel 3 AddOutputFilter DEFLATE html xml php js css <Location /> SetOutputFilter DEFLATE BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html SetEnvIfNoCase Request_URI \\.(?:gif|jpe?g|png)$ no-gzip dont-vary SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzip dont-vary Header append Vary User-Agent env=!dont-vary #对代理的设置 </Location> 下面二个测试网站 http://www.whatsmyip.org/mod_gzip_test/ http://www.gidnetwork.com/tools/gzip-test.php 测试数据对css Original Size: 44 KB Gzipped Size: 10 KB Data Savings: 77.27% 测试数据js Original Size: 6 KB Gzipped Size: 2 KB Data Savings: 66.67% 测试数据php Original Size: 62 KB Gzipped Size: 15 KB Data Savings: 75.81% 上面只是随机拿的几个数据,看的出来,使用了gzip压缩后文件小多了. 另外讲一下,有关squid对gzip的处理 在squid中,对同一个URL只保留一份缓存。对于如果不同browser(是否支持压缩) 如果频繁交替访问,例如:对某个cache住的目标,一个http/1.0请求可能会导致squid强制更新其缓存。但接下来的另一个http/1.1请 求又会导致squid再次更新缓存。这样那squid缓存数据就要频繁更新,这就极大的降低了cache命中率。 不过还好,现实环境中不支持压缩的browser毕竟是很少的情况,所以对于缓存命中率的降低很有限.

WordPress:自定义排序WordPress后台管理菜单和修改WordPress后台登录地址

// 自定义排序WordPress后台管理菜单 (在 WP 3.5.2 测试通过) From wpdaxue.com
function custom_menu_order($menu_ord) {
	if (!$menu_ord) return true;
	return array(
		'index.php', // “仪表盘”菜单
		'edit.php?post_type=question', // 自定义文章类型的菜单
		'edit-comments.php', //“评论”菜单
		'upload.php', //“多媒体”菜单
		'edit.php?post_type=cmp_slider', //自定义文章类型的菜单
		'plugins.php', //“插件”菜单
		'themes.php', //“主题”菜单
		'edit.php?post_type=page', // “页面”菜单
		'edit.php', // “文章”菜单
	);
}
add_filter('custom_menu_order', 'custom_menu_order');
add_filter('menu_order', 'custom_menu_order');
你只需复制顶级菜单的链接(只取/wp-admin/后面的部分),然后添加到 第 4 行下面的数组中,进行排序即可。  
//保护后台登录
add_action('login_enqueue_scripts','login_protection');
function login_protection(){
    if($_GET['word'] != 'press')header('Location: http://www.frankway.net/');
}
这样一来,后台登录的唯一地址就是 http://yoursite/wp-login.php?word=press

WordPress:后台优化(更改字体/固定侧边栏菜单/增强编辑器等)

一、更改后台字体

后台字体中文貌似是宋体或别的,我们可以改成我们喜欢的:
1
2
3
4
5
//更改后台字体
function Bing_admin_lettering(){
	echo'<style type="text/css">*{font-family:"Microsoft YaHei" !important;}</style>';//修改字体
}
add_action('admin_head', 'Bing_admin_lettering');
可以修改第 4 行的 font-family 属性,改成自己喜欢的宋体,默认改成微软雅黑。

二、固定后台管理侧边栏

有时页面太长,就可以固定侧边的菜单栏,去别的页面不用再拉到页面顶部:
1
2
3
4
5
//固定后台管理侧边栏
function Bing_fixed_adminmenuwrap(){
	echo '<style type="text/css">#adminmenuwrap{position:fixed;left:0px;z-index:2;}</style>';
};
add_action('admin_head', 'Bing_fixed_adminmenuwrap');

三、增强默认编辑器

默认编辑器默认不是把所有的按钮都显示出来,导致它很鸡肋,添加下边的代码可以找回这些按钮:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//增强默认编辑器
function Bing_editor_buttons($buttons){
	$buttons[] = 'fontselect';
	$buttons[] = 'fontsizeselect';
	$buttons[] = 'backcolor';
	$buttons[] = 'underline';
	$buttons[] = 'hr';
	$buttons[] = 'sub';
	$buttons[] = 'sup';
	$buttons[] = 'cut';
	$buttons[] = 'copy';
	$buttons[] = 'paste';
	$buttons[] = 'cleanup';
	$buttons[] = 'wp_page';
	$buttons[] = 'newdocument';
	return $buttons;
}
add_filter("mce_buttons_3", "Bing_editor_buttons");
 

四、阻止站内文章互相 Pingback

比如这篇文章,就引用了另一篇本站的文章,导致会出现无用的 Pingback,添加下边的代码可以避免上述情况的出现:
1
2
3
4
5
6
7
8
//阻止站内文章互相Pingback 
function Bing_noself_ping($links) {
	$home = get_option( 'home' );
	foreach ( $links as $l => $link )
	if ( 0 === strpos( $link, $home ) )
	unset($links[$l]);
}
add_action('pre_ping','Bing_noself_ping');

Mysql中count(*),DISTINCT的使用方法和效率研究

 
在处理一个大数据量数据库的时候 突然发现mysql对于count(*)的不同处理会造成不同的结果 比如执行 SELECT count(*) FROM tablename 即使对于千万级别的数据mysql也能非常迅速的返回结果 而对于 SELECT count(*) FROM tablename WHERE..... mysql的查询时间开始攀升 仔细查阅累下手册,发现当没有WHERE语句对于整个mysql的表进行count运算的时候 MyISAM类型的表中保存有总的行数,而当添加有WHERE限定语句的时候Mysql需要对整个表进行检索 从而得出count的数值 突然又想起来看到的不少新兴的php程序对于count的处理并没有很好的意识到这点 记录下 顺便提下mysql的DISTINCT的关键字有很多你想不到的用处 1.在count 不重复的记录的时候能用到 比如SELECT COUNT( DISTINCT id ) FROM tablename; 就是计算talbebname表中id不同的记录有多少条 2,在需要返回记录不同的id的具体值的时候可以用 比如SELECT DISTINCT id FROM tablename; 返回talbebname表中不同的id的具体的值 3.上面的情况2对于需要返回mysql表中2列以上的结果时会有歧义 比如SELECT DISTINCT id, type FROM tablename; 实际上返回的是 id与type同时不相同的结果,也就是DISTINCT同时作用了两个字段,必须得id与tyoe都相同的才被排除了,与我们期望的结果不一样 4.这时候可以考虑使用group_concat函数来进行排除,不过这个mysql函数是在mysql4.1以上才支持的 5.其实还有另外一种解决方式,就是使用 SELECT id, type, count(DISTINCT id) FROM tablename 虽然这样的返回结果多了一列无用的count数据(或许你就需要这个我说的无用数据) 返回的结果是 只有id不同的所有结果和上面的4类型可以互补使用,就是看你需要什么样的数据了

MySQL优化之COUNT(*)效率

MySQL优化之COUNT(*)效率

刚给一个朋友解决他写的Discuz!插件的问题,说到MySQL的COUNT(*)的效率,发现越说越说不清楚,干脆写下来,分享给大家。 COUNT(*)与COUNT(COL) 网上搜索了下,发现各种说法都有: 比如认为COUNT(COL)比COUNT(*)快的; 认为COUNT(*)比COUNT(COL)快的; 还有朋友很搞笑的说到这个其实是看人品的。 在不加WHERE限制条件的情况下,COUNT(*)与COUNT(COL)基本可以认为是等价的; 但是在有WHERE限制条件的情况下,COUNT(*)会比COUNT(COL)快非常多; 具体的数据参考如下:   mysql> SELECT COUNT(*) FROM cdb_posts where fid = 604; +————+ | COUNT(fid) | +————+ | 79000 | +————+ 1 row in set (0.03 sec) mysql> SELECT COUNT(tid) FROM cdb_posts where fid = 604; +————+ | COUNT(tid) | +————+ | 79000 | +————+ 1 row in set (0.33 sec) mysql> SELECT COUNT(pid) FROM cdb_posts where fid = 604; +————+ | COUNT(pid) | +————+ | 79000 | +————+ 1 row in set (0.33 sec) COUNT(*)通常是对主键进行索引扫描,而COUNT(COL)就不一定了,另外前者是统计表中的所有符合的纪录总数,而后者是计算表中所有符合的COL的纪录数。还有有区别的。 COUNT时的WHERE 简单说下,就是COUNT的时候,如果没有WHERE限制的话,MySQL直接返回保存有总的行数 而在有WHERE限制的情况下,总是需要对MySQL进行全表遍历。 优化总结: 1.任何情况下SELECT COUNT(*) FROM tablename是最优选择; 2.尽量减少SELECT COUNT(*) FROM tablename WHERE COL = ‘value’ 这种查询; 3.杜绝SELECT COUNT(COL) FROM tablename WHERE COL2 = ‘value’ 的出现。

如果表没有主键,那么count(1)比count(*)快。 如果有主键,那么count(主键,联合主键)比count(*)快。 如果表只有一个字段,count(*)最快。

MySQL数据库查询优化

上两周一直想办法提高查询速度,取得一点效果,解决了部分问题,记下来以便将来自己查看。 由于公司没有专门的DBA,我自己对mysql数据库也不是很熟悉,而且这个JAVA开发的网络审计系统的管理系统,是经过了N多人几年时间的修修改改,今天到我们手里,要改成能支持大流量情况的版本,所以对我们这个只有几个人的JAVA组来说,确实是个难题。 这个大流量的情况在以前的文章里也提到过,就是要支持每秒钟处理1G左右的网络数据包,HTTP协议的数据包最多,因此HTTP协议分析模块的流水日志表记录最大,据估算可能到达一天4000万条记录,采用一天一张表,那也是很大的,我看了.MYD文件大小,已经是8G多了。 而我们管理系统查询日志记录时,对好几个字段都要进行条件查询,而且有几个字段长度达到256,在8G这么大的表里查询一个字符串,如果找不到,那必定从头要查到尾,速度慢得根本受不了。客户还要好几个字段一起设置条件来查询,这样基本上是二三十分钟都出不来,系统可用性极差。 我采用的方法是以测试为主,同时看JAVA代码,通过Log4j和Perf4j日志,看每个sql语句使用的时间,寻找性能瓶颈,然后有的放矢地进行优化。 对查询最有效果的优化,自然是建立索引了,ID自然是自增、主键,这个前人已经做了;从where语句分析,时间字段作为查询条件很多,时间是8字节,而且不重复,设置索引比较适合。我把时间设置为索引,有一点效果,但不大,估算一下:8 * 4000 0000 = 320 000 000 字节,4000万记录的表仅仅时间一个字段的索引将是320M,这还仅仅是我们上百张表的一张表而已(客户要求我们至少保存3个月记录)。 建立索引能起到一定作用,但还是解决不了我们的问题。物理表建立不能再缩短时间了,因为一天一张表,3个月就91~92张表,30个协议模块就得2700多,这仅仅是协议流水日志表,还有其它表呢。 也不能把客户要求做成条件的字段都设置成索引,那索引表将和原表差不多大,索引就失去意义了。在数据库本身上优化,想去想来实在一下子想不到好办法,感觉数据量大了,就算在Oracle上也没有什么神奇办法吧。 我最后采用分段查询的方法,就是4000万条数据,我不管你设置什么条件来查询,我都是平均划为成N段来查询,比如400万为一段,在页面上提供一个下拉单:0~400万,400~800万,…,3600~4000万,虽然查询比较麻烦一点,但每段查询的速度大大提高,控制在30秒左右,牺牲一些可用性,总比30分钟还查不出来好吧。 流水日志可以采用分段查询解决,但客户要求的各种统计呢,这不能说分段统计,别人要统计2天的,你分开是不行的。 以前已经采用了一次预统计,预先定时在后台对流水日志表进行统计一次,保存到预统计表,等用户来查询时,从预统计表进行各种查询—-这个做法好,不得不夸下前任开发人员。 但现在形势不同了,因为预统计表是采用一个月一张的,就现在流水日志表的规模,那预统计表可能一张表超过4000万,具体看客户网络数据的分布情况,不好估计。 最后我和同事们对统计模式详细分析,一个同事提出再在预统计表基础上进行二次预统计,我们估算了一下,基本上等用户来查询时,所面对的表已经很小了,最多几千条记录,很快了。 解决统计查询过程中,让我体会到详细分析业务流程细节,作出相应的优化,有时是可以解决问题的。 总体上来说,对数据库查询的优化,我们采取了一些常规的优化之后,如果还没有取得想要的效果,我们有时候不必硬碰硬去优化查询本身,改变一下使用模式,找找业务处理流程是否还有可修改的,说不定就轻松解决了存在的难题。 还有就是主管要把整个开发组积极性调动起来,大家一起测试、分析、想办法、验证,最后一致确定一个可行的方案,然后大家分头去不打折扣的实现。 转自php100