一次Dsicuz 6.0 Mysql 优化经历
单位论坛使用了Discuz 6.0 架设的论坛,初步统计数据:
分区和版块(cdb_forums 表 )共 109 个
主题贴(cdb_threads) 18 万
帖子表(cdb_posts 表 ) 152 万
表现情况是,当用户登录后,论坛首页加载非常缓慢,竟然需要3 - 4 秒 , 而在以下情况下访问速度正常:
1 . 以游客身份浏览所有页面(包含论坛首页,贴子列表页,版块首页)很正常。
2 . 登录后浏览其它页面(即非首页)很正常。
经过层层检查,将瓶颈锁定在了论坛安装的“火狼”插件,此插件用于在Discuz 6.0 首页显示一些推荐的贴子,发贴排行等等。
虽然“火狠”插件后台提供了数据缓存功能,打开数据缓存后,首页加载速度很正常,但因为实时性要求,数据又不能缓存,故只能从SQL 优化入手。
正常的思路就是找出可能有问题的SQL , 再检查其执行计划,反复验证之。
现在的问题是: 我现在根本不知道论坛究竟作了哪些SQL 查询! 又因为论坛已经投入使用,无法擅自修改程序(影响其它用户浏览)。
为此,我使用了一个条件输出SQL 语句的调整功能:
1. 下载discuz 6.0 的 include/db_mysql.class.php 这个文件是 dz6.0 的核心数据库访问类,所有 SQL 查询都由此类处理。
2. 找到 function query($sql, $type = '') {
将它下面的
global $debug, $discuz_starttime, $sqldebug, $sqlspenttimes;
修改为
global $debug, $discuz_starttime, $sqldebug, $sqlspenttimes,$discuz_uid;
在以上行后面加一行:
if($discuz_uid == 1041538) {
echo $sql."\n\n" ;
}
1041538是我在论坛的用户 id, 换成你自己的 uid ,然后保存并上传覆盖论坛原文件。
这时,以你自己的论坛帐号登录并浏览论坛首页,应该可以显示出discuz 6 的 SQL 查询, 逐个复制这些 SQL 语句, 到 PHPAyAdmin 或 Mysql 命令行下查询,最终发现有问题的语句是:
SELECT t.tid, t.author, t.authorid, t.subject, t.dateline, t.lastpost, t.lastposter,
t.views, t.replies, t.highlight, t.highlight, f.name FROM cdb_threads t, cdb_forums f
WHERE f.fid=t.fid AND t.displayorder >-1 ORDER BY t.dateline DESC LIMIT 0,10
使用phpmyadmin 执行这个语句结果:
果不其然,查询用时2.0527 秒, 点击 PHPmyadmin 右下角的 Explain SQL ,检查执行计划,输出结果如下:
上述图中的 t 表,也就是 cdb_threads 表,其扫描的行数为 174984 , 首页将疑点锁定在这 t 表的查询上,为验证 t 表的查询,在不连接 f 表 ( 即 cdb_forums) 的情况,单独执行其查询:
select t.tid, t.author, t.authorid, t.subject, t.dateline, t.lastpost, t.lastposter,
t.views, t.replies, t.highlight, t.highlight from cdb_threads t
where t.displayorder not in(-1,-2) ORDER BY t.dateline DESC LIMIT 0,10
phpmyadmin执行结果如下:
用时0.0005 秒,速度非常正常,那么可疑的查询只可能是在 f 表 where 过滤上:
SELECT t.tid, t.author, t.authorid, t.subject, t.dateline, t.lastpost, t.lastposter,
t.views, t.replies, t.highlight, t.highlight, f.name FROM cdb_threads t,
cdb_forums f WHERE f.fid=t.fid AND f.fid not in (0)
AND t.displayorder not in (-1,-2) ORDER BY t.dateline DESC LIMIT 0,10
为此,我逐个去掉f 表的 where 条件,再测试其效率。经过反复测试,发现去去掉 f.fid not in (0) 条件时,查询速度很正常,根据其意义,是查询 cdb_forums 表中 fid 字段不等于 0 的记录。
而cdb_forums 表中 fid 字段的定义是:
SMALLINT, 正整数,自增主键。
可见,fid 定义成了正整数,那么这里的 fid not in(0) 限定将没有任何意义,因为 NOT IN 之类的查询,是无法使用索引的,那么读者可能认为 fid>0 是否可使用索引? 这得看情况,因为 fid 已经被定义成了正整数,那么 fid>0 仍然不会使到索引,以下的查询可以验证之:
既然 fid 已经是正整数,那么, fid Not in(0) 完全没有意义,我们将这个条件去掉:
现在的查询,速度是0.0005 秒, 终于解决之。
那么我的解决方法就是修改plugins/firewolf_indextoplist/threadfocus.php , 找到其中的 fid Not in(0) 限定 , 将其全部删除之 .
如果站在程序员的角度,以上的方案完全可以进行尝试优化,避免与cdb_forums 表联合查询,仅仅为了从 fid 得到 cdb_forums.name 而进行联合查询,的确是得不偿失,完全可以根据需要将 cdb_forums 表中的数据缓存成数组,如:
$fnames = array(
1 => '谈天说地 ',
2 => '休闲一刻 ',
...
);
$fnames[2]即可取得指定 fid 的 name, 何乐而不为呢?
经过以上处理, 加载速度已经提高了不少 , 但发现还是慢 , 重复以上方法 , 找到以下 SQL 的查询时间过长 :
SELECT t.tid, t.author, t.authorid, t.subject, t.dateline, t.lastpost,
t.lastposter, t.views, t.replies, t.highlight, t.highlight, f.name
FROM cdb_threads t, cdb_forums f
WHERE f.fid=t.fid AND t.closed NOT LIKE 'moved|%' AND t.replies >=1
AND t.displayorder >-1 ORDER BY t.lastpost DESC LIMIT 0,10
经过检查, 是因为 cdb_threads 的 lastpost 字段没有加索引 , 为其增加索引 , 一切 OK.
通过这个案例,你应该至少明白两个索引原理:
1. NOT IN, <> , NOT LIKE 之类的查询,是无法使用索引的
2. 某个字段如果定义成正整数, 那么 >0 之类的查询也是无法使用索引的(既然字段是非 0 值, 那么如此的限定只能是废话)。
3. 有时 , 方法比知识更重要
相关推荐
在信息技术领域,VB6.0(Visual Basic 6.0)是一个经典的编程语言版本,而MySQL则是一个流行的开源关系数据库管理系统。在编写应用程序时,经常会涉及到数据库的操作,比如查询、更新、删除和插入等。本文将详细地...
VC6.0是一款经典且功能强大的C++集成开发环境,而MySQL则是一种广泛使用的开源关系型数据库管理系统。通过将两者结合,开发者可以利用C++编程语言实现对MySQL数据库的高效数据处理。 首先,你需要确保已经安装了VC...
动网论坛6.0郭嘉优化版是针对动网论坛基础版本进行的一次深度优化和升级,旨在提升用户在论坛社区类应用中的体验,兼顾速度与安全性。这款产品结合了SP1和SP2的更新内容,对系统性能进行了全方位的改进,使得论坛...
MySQL 6.0是MySQL数据库管理系统的一个早期版本,发布于2005年。尽管现在已经有了更新的版本,如MySQL 8.x,但在某些特定场景下,如旧项目维护或对硬件资源有限的环境,仍可能使用MySQL 6.0。这个版本带来了许多改进...
9. 应用实例:可以通过具体的实例来展示VB6.0如何连接MySQL数据库,例如开发一个简单的地址簿管理系统,其中数据库部分由MySQL负责,前端界面通过VB6.0的表单和控件与用户进行交互。 文档中可能还会有对VB6.0连接...
VC6.0是Microsoft推出的一个经典的C++集成开发环境,而MySQL则是一种广泛使用的开源关系型数据库管理系统。结合两者,我们可以创建高效的C++应用程序,利用MySQL的强大功能来存储和处理数据。 首先,我们需要安装...
在VB6.0(Visual Basic 6.0)中连接MySQL数据库是一项常见的任务,尤其对于那些需要构建桌面应用程序并利用远程或本地MySQL服务器存储数据的开发者来说。本篇将详细介绍如何使用VB6.0与MySQL数据库进行交互,并重点...
首先,为了在VC6.0中与MySQL进行交互,我们需要安装一个支持MySQL的C++库,例如MySQL Connector/C++。这个库提供了C++接口,使得VC6.0能够调用MySQL的API来执行SQL查询和管理数据库。 1. **安装MySQL Connector/C++...
基于VC6.0的MYSQL测试,可以进行数据库的增,删,减,数据库是基于MYSQL5.0的,如果连接不上数据库,将自己安装的数据库LIB下的libsql.dll,文件复制到程序就可以连接了,测试编译正确,
MySQL 6.0是一款广泛应用的关系型数据库管理系统,其绿色版是指无需安装,只需解压缩就能使用的版本,非常适合在没有管理员权限或临时环境下的快速部署。本篇将详细讲解绿色版MySQL 6.0的使用方法及其核心知识点。 ...
MySQL Server 6.0是MySQL数据库管理系统的一个较早版本,由瑞典的MySQL AB公司开发,后被Sun Microsystems收购,最终成为Oracle公司的一部分。这个版本在MySQL的发展历程中扮演了重要的角色,因为它引入了许多新特性...
本文将详细讲解如何使用VB6.0(Visual Basic 6.0)编程语言与MySQL数据库结合,构建一个简单而实用的小型超市管理系统,包括系统的主要功能、设计思路和技术实现。 一、系统概述 VB6.0是微软公司推出的可视化编程...
MySQL 6.0是MySQL数据库管理系统的一个早期版本,尽管它现在已经过时,但对于学习和理解数据库安装过程仍有价值。在Windows环境下安装MySQL 6.0的步骤如下: 首先,你需要从MySQL的官方网站或其他可靠的下载源获取...
MySQL 6.0数据库安装包是一个为用户提供高效数据存储解决方案的软件,尤其适用于中小型企业或个人网站。MySQL因其开源、免费、稳定和高性能的特点,在IT领域广泛应用。此安装包包括了MySQL 6.0版本的数据库服务器,...
把MySql.Data.dll放到工程debug文件夹下,然后在应用工程中引用组件:MySql.Data.dll 在代码页中:using MySql.Data.MySqlClient;
Solr 6.0 是一个流行的开源全文搜索引擎,它提供了高效、可扩展的搜索和分析功能。MySQL 是广泛使用的开源关系型数据库管理系统。将 Solr 集成与 MySQL,可以实现对 MySQL 数据库中的数据进行实时索引和快速检索,...
MySQL 6.0是Oracle公司出品的一款开源的关系型数据库管理系统,它以其高效、稳定和易于管理的特点,在IT行业中被广泛应用于各种规模的项目。SQLyog则是Webyog公司开发的一款直观的图形化MySQL数据库管理工具,它为...
自动关联一些函数,可以方便开发人员开发程序。