当前位置

修改MediaWiki的动态页面列表DPL设置降低MySQL负载

James Qi 在 2017年12月9日 - 19:33 提交

  最近一直在为降低MySQL服务器负载努力,Drupal网站中主要是排查Views引起的性能问题,而MediaWiki中也有一个与Drupal的Views对应的工具:Dynamic Page List (DPL动态页面列表),既可以灵活运用得到希望的信息展示效果,但同时也容易引起数据库负载过高、性能下降。

  当网站打开很慢的时候,还是需要查看阿里云RDS数据管理控制台DMS(Data Management Service),查看诊断报告或者当前实例会话,查看慢查询语句,例如发现大量这样的语句:

SELECT DISTINCT `jinglepage`.page_namespace AS page_namespace,
       `jinglepage`.page_title AS page_title,
       `jinglepage`.page_id AS page_id,
       rev_user,
       rev_user_text,
       rev_comment,
       rev_timestamp
  FROM `jinglerevision` AS rev,
       `jinglepage`
  INNER JOIN `jinglecategorylinks` AS cl0 ON `jinglepage`.page_id= cl0.cl_from
   AND(cl0.cl_to= '骗子号码')
 WHERE 1= 1
   AND `jinglepage`.page_namespace IN('0')
   AND `jinglepage`.page_is_redirect= 0
   AND `jinglepage`.page_id= rev.rev_page
   AND rev.rev_timestamp=(
SELECT MIN(rev_aux.rev_timestamp)
  FROM `jinglerevision` AS rev_aux
 WHERE rev_aux.rev_page= rev.rev_page)
 ORDER BY rev_timestamp DESC
 LIMIT 500 OFFSET 0

  这是我们一个叫做“查号吧”网站中列出网友举报的[[骗子号码]]的页面生成需要的MySQL查询语句,这500个最新号码是用DPL扩展程序列出的,Wiki中的源代码如下:

{{#dpl:
|namespace=
|ordermethod = firstedit
|order       = descending
|addeditdate = true
|category    = 骗子号码
|adduser = true
|mode = userformat
|listseparators= ,¶# %DATE%: [[%PAGE%]] - %USER%
}}

  没有想到其中列出首次编辑时间、增加用户名称等会让SQL很要复杂一些起来,运行速度变慢,可以加入debug=3这个参数来显示SQL语句以便调试。我后来采取了几个措施:

  • 去掉了adduser,不显示%USER%信息了,这样还可以避免用户怕IP暴露;
  • 排序条件从firstedit首次编辑时间改为pagetouched,也就是页面更新时间(有可能是其使用的模板变化引起);
  • 显示first edit date变为显示page touched date;
  • 增加了redirects重定向页面也可以显示列表。

  具体源代码改为:

{{#dpl:
|ordermethod = pagetouched
|order       = descending
|addpagetoucheddate = true
|category    = 骗子号码
|redirects = include
|mode = userformat
|listseparators= ,¶# %DATE%: [[%PAGE%]]
|debug = 3
}}

  这样可以看到SQL语句变为了:

SELECT DISTINCT `jinglepage`.page_namespace AS page_namespace,
       `jinglepage`.page_title AS page_title,
       `jinglepage`.page_id AS page_id,
       `jinglepage`.page_touched AS page_touched
  FROM `jinglepage`
  INNER JOIN `jinglecategorylinks` AS cl0 ON `jinglepage`.page_id= cl0.cl_from
   AND(cl0.cl_to= '骗子号码')
 WHERE 1= 1
 ORDER BY page_touched DESC
 LIMIT 500 OFFSET 0

  明显比前面的查询条件简单,实测运行时间从5004 ms下降到2902 ms。这样显示的列表没有了首次编辑时间,从功能上说比原来稍微差一点,但不改动模板的情况下,页面更新时间和首次编辑时间是相同的,所以也还不太影响最后的显示效果。

  还有其它页面(例如:[[首页]])和模板(例如:[[模板:分类骗子]]、[[模板:省份手机三位]]、[[模板:省份手机四位]]、[[模板:省份手机五位]]、[[模板:运营商手机三位]]、[[模板:运营商手机四位]]等)我也做了类似改动,综合起来对改善服务器负载应该有好的作用。

  MediaWiki的DPL列表功能没有Drupal的Views灵活强大,也不是很方便控制最后的SQL语句,只好多查看手册,用一些条件来尝试,对SQL语句运行进行对比,观察RDS MySQL服务器的负载情况和诊断报告,从慢查询是否减少来判断效果。

  补充参考资料:

  其中几个可能用到的技巧:

  • 调试SQL语句:增加|debug=3
  • 去掉DISTINCT:distinct=false
  • 增加了redirects重定向页面也可以显示列表:redirects=true
  • 不要排序:ordermethod=none
  • 返回数量:可改为较小或为1:
  • 尽量用Title而不用其他字段构造内容显示;
  • 尽量少返回的数据,或者如果需要的话设定为1:count=10;
  • 简化分类,能不用的分类尽量不用,可结合namespace=example, matchtitle=example 来生成列表

添加新评论

Plain text

  • 不允许使用HTML标签。
  • 自动将网址与电子邮件地址转变为链接。
  • 自动断行和分段。