2013-05-08 98 views
3

我需要抽出一点我的查询,因为它在大型数据库上花费太长时间。MySql:需要改进查询的性能

我有以下表

vb_user 

+++++++++++++++++++++++++++++++++

++用户ID ++的用户名+职位++

++++++++++++++++++++++++++++++++ +

vb_post 

++++++++++++++++++++++++

++用户ID ++界线++

++++++++++++++++++++++++

我用这个查询

SELECT VBU.userid AS USER_ID 
, VBU.username AS USER_NAME 
, COUNT(VBP.userid) AS NUMBER_OF_POSTS_FOR_30_DAYS 
      , FROM_UNIXTIME(VBU.joindate) as JOIN_DATE 
     FROM vb_user AS VBU 
     LEFT JOIN vb_post AS VBP 
     ON VBP.userid = VBU.userid 
      WHERE VBU.joindate BETWEEN '__START_DATE__' AND '__END_DATE__' 
       AND VBP.dateline BETWEEN VBU.joindate AND DATE_ADD(FROM_UNIXTIME(VBU.joindate), INTERVAL 30 DAY) 
      GROUP BY VBP.userid 
      ORDER BY NUMBER_OF_POSTS_FOR_30_DAYS DESC" 

我不得不选择谁已经公布,从他们加入,直到30天后大多数用户.....我无法弄清楚如何做到这一点的withouth的功能FROM_UNIXTIME ..

但它需要很多时间。有关如何提高查询性能的任何想法?

这里是输出解释

id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra 
1,SIMPLE,VBP,index,userid,threadid_visible_dateline,18,NULL,2968000,"Using where; Using index; Using temporary; Using filesort" 
1,SIMPLE,VBU,eq_ref,PRIMARY,PRIMARY,4,vb_copilul.VBP.userid,1,"Using where" 

这里是关于表的信息

Table,"Create Table" 
vb_user,"CREATE TABLE `vb_user` (
    `userid` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `username` varchar(100) NOT NULL DEFAULT '', 
    `posts` int(10) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`userid`), 
    KEY `usergroupid` (`usergroupid`), 
) ENGINE=MyISAM AUTO_INCREMENT=101076 DEFAULT CHARSET=latin1" 

Table,"Create Table" 
vb_post,"CREATE TABLE `vb_post` (
`postid` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`threadid` int(10) unsigned NOT NULL DEFAULT '0', 
`parentid` int(10) unsigned NOT NULL DEFAULT '0', 
`username` varchar(100) NOT NULL DEFAULT '', 
`userid` int(10) unsigned NOT NULL DEFAULT '0', 
`title` varchar(250) NOT NULL DEFAULT '', 
`dateline` int(10) unsigned NOT NULL DEFAULT '0', 
`pagetext` mediumtext, 
`allowsmilie` smallint(6) NOT NULL DEFAULT '0', 
`showsignature` smallint(6) NOT NULL DEFAULT '0', 
`ipaddress` char(15) NOT NULL DEFAULT '', 
`iconid` smallint(5) unsigned NOT NULL DEFAULT '0', 
`visible` smallint(6) NOT NULL DEFAULT '0', 
`attach` smallint(5) unsigned NOT NULL DEFAULT '0', 
`infraction` smallint(5) unsigned NOT NULL DEFAULT '0', 
`reportthreadid` int(10) unsigned NOT NULL DEFAULT '0', 
PRIMARY KEY (`postid`), 
KEY `userid` (`userid`), 
KEY `threadid` (`threadid`,`userid`), 
KEY `threadid_visible_dateline` (`threadid`,`visible`,`dateline`,`userid`,`postid`), 
KEY `dateline` (`dateline`), 
KEY `ipaddress` (`ipaddress`) 
) ENGINE=MyISAM AUTO_INCREMENT=3009320 DEFAULT CHARSET=latin1" 
+1

你有没有做对的查询的解释?如果是这样,那告诉你什么? – 2013-05-08 10:31:38

+0

yay在EXPLAIN上。你能否发布完整的表格定义?最好使用'SHOW CREATE TABLE vb_user'和'SHOW CREATE TABLE vb_post'的结果,甚至可以使用'INSERT INTO ....'语句形式的一些示例数据。 – VolkerK 2013-05-08 10:43:17

回答

3

有两件事情可以做,以提高查询:

  • 不要将VBP.datetime转换为unix时间。直接使用带日期的BETWEEN查询。在您的查询中,服务器必须转换数据库中的所有日期以进行比较,而不是使用本机类型。如果您总是使用datetime列作为unix时间戳,那么将其声明为Double(我认为?)而不是DATETIME(或TIMESTAMP - 无论您选择了什么)。这样你也可以加速其他操作。
  • 将索引添加到datetime列以确保查询之间足够快。

其他的一切看起来不错

+0

我刚刚看到了解释并创建了添加的表语句 - 是的,日期行列已经是int类型。查看说明查询 - 它确实使用了一个非常复杂的键,但仍能扫描数千行。因此,请尝试删除转换,然后尝试删除该threadid_visible_dateline键 - 它可以强制它使用更好的键。 – 2013-05-08 11:22:48

+0

真的,它需要在日期和用户ID上的索引。 – symcbean 2013-05-08 11:28:01

+0

当然,那么应该有一个,但在太多的领域添加索引可能是有害的!所以我的建议是首先放下那个索引,看看它是怎么回事。之后(你是对的)尝试在这两个字段上添加一个索引。我不确定MySQL在选择索引时有多聪明 - 必须试着看看它是否会更喜欢那个索引。 – 2013-05-08 11:40:48