2010-08-24 84 views
0

这是我在其中一个网站上经常使用的SELECT查询的一个广泛示例。我们的主机缓慢加载页面时间的问题非常严重,所以我正在尽我所能优化网站使用的每一段代码。谈到MySQL我不是专家,所以我希望你们中的一些人可能会有帮助。这里是我试图优化多一点查询 -MySQL选择优化帮助?

Select ID, Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9, Col10, Col11, Col12, Col13, Col14, Col15 From table_1 
Where Active = '1' And Col2 LIKE '%Cat%' And Col3 <> 'blah' And Col3 <> 'blah1' And Col3 <> 'blah2' And Col3 <> 'blah3' And Col3 <> 'blah4' And Col3 <> 'blah5' And Col3 <> 'blah6' 
And ID Not In (Select t2ID From table_2 Where table_2.t2ID = table_1.ID And table_2.Col1 = '1' And table_2.Col2 = '1') 
And ID Not In (Select t3ID From table_3 Where table_3.t3ID = table_1.ID And table_3.Col1 = '1') 
And ID Not In (Select t4ID From table_4 Where table_4.t4ID = table_1.ID And table_4.Col1 = '1') 

基本上它检查1台(TABLE_1)和拉那场比赛,在TABLE_2,TABLE_3和TABLE_4未找到的所有行。我相信除了多个子选择之外,还有一种更有效的方法来完成此操作。任何帮助是极大的赞赏!在此先感谢:)

更新:基本上我很想知道的是,有没有比在查询中的多个子选择更快?我确信有一种方法可以从一个表中获取不在多个其他表中存在的结果,这比子选择效率高得多......表之间唯一的共同点是来自table_1的ID是与其他3个表中的另一列完全相同(这是我目前使用子选择检查它的原因)。不幸的是,我只是不知道更有效的方法来做这个查询是...迄今为止感谢大家的输入!

表格布局

mysql> show create table campaigns\G 
*************************** 1. row *************************** 
Table: campaigns 
Create Table: CREATE TABLE `campaigns` ( 
`ID` int(11) NOT NULL auto_increment, 
`CreatedOn` datetime NOT NULL, 
`AddedBy` varchar(75) default NULL, 
`pCampaignName` varchar(255) default NULL, 
`CampaignName` varchar(255) default NULL, 
`CampaignValue` decimal(65,2) default '0.00', 
`CampaignPayout` decimal(65,2) NOT NULL default '0.00', 
`CampaignT` double NOT NULL default '0', 
`CampaignSD` double NOT NULL default '0', 
`ReportingTime` varchar(255) default NULL, 
`CampaignExpiration` varchar(100) default NULL, 
`DurationType` varchar(100) default NULL, 
`Countries` varchar(100) default NULL, 
`CampaignDescription` longtext, 
`CampaignRequirements` longtext, 
`CampaignType` varchar(50) default NULL, 
`CampaignID` varchar(255) default NULL, 
`BannerImageWidth` int(10) NOT NULL default '0', 
`BannerImageHeight` int(10) NOT NULL default '0', 
`BannerImageURL` varchar(255) default NULL, 
`BannerImageAlternateText` varchar(255) default NULL, 
`DisplayBanner` int(1) NOT NULL default '0', 
`CampaignCode` longtext, 
`CampaignURL` longtext, 
`CampaignActive` int(1) NOT NULL default '0', 
`Status` varchar(255) default NULL, 
`Affiliate` varchar(255) default NULL, 
`NewOfferEmailSent` int(1) unsigned NOT NULL default '0', 
`NumberApproved` double(65,2) NOT NULL default '0.00', 
`NumberLeads` double NOT NULL default '0', 
`ThumbsUp` double NOT NULL default '0', 
`ThumbsDown` double NOT NULL default '0', 
`CampaignPoints` double NOT NULL default '0', 
`UserRatingUp` double NOT NULL default '0', 
`UserRatingDown` double NOT NULL default '0', 
PRIMARY KEY (`ID`) 
) ENGINE=MyISAM AUTO_INCREMENT=1608 DEFAULT CHARSET=utf8 
1 row in set (0.09 sec) 

mysql> show indexes from campaigns\G 
*************************** 1. row *************************** 
Table: campaigns 
Non_unique: 0 
Key_name: PRIMARY 
Seq_in_index: 1 
Column_name: ID 
Collation: A 
Cardinality: 1596 
Sub_part: NULL 
Packed: NULL 
Null: 
Index_type: BTREE 
Comment: 
1 row in set (0.10 sec) 

mysql> 
mysql> show create table acampaigns\G 
*************************** 1. row *************************** 
Table: acampaigns 
Create Table: CREATE TABLE `acampaigns` ( 
`ID` int(11) NOT NULL auto_increment, 
`CreatedOn` datetime NOT NULL, 
`CampaignName` varchar(255) default NULL, 
`CampaignRequirements` longtext, 
`CampaignURL` longtext, 
`CampaignValue` decimal(65,2) NOT NULL, 
`CampaignPayout` decimal(65,2) NOT NULL, 
`CampaignReferralCommissionTier1` decimal(65,2) NOT NULL default '0.20', 
`CampaignReferralCommissionTier2` decimal(65,2) NOT NULL default '0.10', 
`CampaignT` double NOT NULL default '0', 
`CampaignSD` double NOT NULL default '0', 
`CampaignType` varchar(255) default NULL, 
`CampaignID` varchar(100) default NULL, 
`CampaignExpiration` varchar(100) default NULL, 
`CampaignReturnStatus` varchar(100) default NULL, 
`CampaignStatus` varchar(255) default NULL, 
`pCampaignID` int(11) NOT NULL, 
`pCampaignName` varchar(255) default NULL, 
`pUserID` int(11) NOT NULL, 
`pUsername` varchar(75) default NULL, 
`pUserIPAddress` varchar(30) default NULL, 
`ApprovedOn` datetime NOT NULL, 
`MarkedDone` int(1) NOT NULL default '0', 
`Notes` longtext, 
`PaidOn` datetime default NULL, 
`cBonus` decimal(65,2) NOT NULL default '0.00', 
`ReversedReason` varchar(255) default NULL, 
`CampaignPoints` double NOT NULL default '0', 
`Affiliate` varchar(255) default NULL, 
`RC1Paid` int(1) unsigned NOT NULL default '0', 
`RC2Paid` int(1) unsigned NOT NULL default '0', 
PRIMARY KEY (`ID`) 
) ENGINE=MyISAM AUTO_INCREMENT=10996 DEFAULT CHARSET=utf8 
1 row in set (0.44 sec) 

mysql> show indexes from acampaigns\G 
*************************** 1. row *************************** 
Table: acampaigns 
Non_unique: 0 
Key_name: PRIMARY 
Seq_in_index: 1 
Column_name: ID 
Collation: A 
Cardinality: 8936 
Sub_part: NULL 
Packed: NULL 
Null: 
Index_type: BTREE 
Comment: 
1 row in set (0.09 sec) 

mysql> 
mysql> show create table bcampaigns\G 
*************************** 1. row *************************** 
Table: bcampaigns 
Create Table: CREATE TABLE `bcampaigns` ( 
`ID` int(11) NOT NULL auto_increment, 
`CreatedOn` datetime NOT NULL, 
`pCampaignID` int(11) NOT NULL, 
`ReportedByUserID` int(11) NOT NULL, 
`Status` varchar(255) default NULL, 
`Notes` longtext, 
PRIMARY KEY (`ID`) 
) ENGINE=MyISAM AUTO_INCREMENT=375 DEFAULT CHARSET=utf8 
1 row in set (0.08 sec) 

mysql> show indexes from bcampaigns\G 
*************************** 1. row *************************** 
Table: bcampaigns 
Non_unique: 0 
Key_name: PRIMARY 
Seq_in_index: 1 
Column_name: ID 
Collation: A 
Cardinality: 0 
Sub_part: NULL 
Packed: NULL 
Null: 
Index_type: BTREE 
Comment: 
1 row in set (0.08 sec) 

mysql> 
mysql> show create table icampaigns\G 
*************************** 1. row *************************** 
Table: icampaigns 
Create Table: CREATE TABLE `icampaigns` ( 
`ID` int(11) NOT NULL auto_increment, 
`CreatedOn` datetime NOT NULL, 
`pCampaignID` int(11) default NULL, 
`IgnoredByUserID` int(11) default NULL, 
PRIMARY KEY (`ID`) 
) ENGINE=MyISAM AUTO_INCREMENT=567 DEFAULT CHARSET=utf8 
1 row in set (0.09 sec) 

mysql> show indexes from icampaigns\G 
*************************** 1. row *************************** 
Table: icampaigns 
Non_unique: 0 
Key_name: PRIMARY 
Seq_in_index: 1 
Column_name: ID 
Collation: A 
Cardinality: 532 
Sub_part: NULL 
Packed: NULL 
Null: 
Index_type: BTREE 
Comment: 
1 row in set (0.40 sec) 

mysql> 
mysql> explain Select ID, CreatedOn, pCampaignName, 
CampaignName, CampaignRequirements, CampaignURL, Countries, 
CampaignPayout, CampaignPoints, CampaignT, CampaignSD, CampaignType, 
ReportingTime, NumberApproved, NumberLeads 
From campaigns 
-> Where CampaignActive = '1' And CampaignType LIKE 'Cat%' 
And CampaignType <> 'DS' And CampaignType <> 'CC' And CampaignType <> 'PC' 
And CampaignType <> 'PC2' And CampaignType <> 'GCC' And CampaignType <> 'G' 
And CampaignType <> 'R' 
-> And ID Not In (Select pCampaignID From acampaigns 
Where campaigns.ID = acampaigns.pCampaignID And MarkedDone = '1' And campaigns.pUserID = '1') 
-> And ID Not In (Select pCampaignID From bcampaigns 
Where bcampaigns.pCampaignID = campaigns.ID And bcampaigns.ReportedByUserID = '1') 
-> And ID Not In (Select pCampaignID From icampaigns 
Where icampaigns.pCampaignID = campaigns.ID And icampaigns.IgnoredByUserID = '1') 

回答

0

你有没有试图解释你的查询。如果您不熟悉EXPLAIN,它将生成一个报告,显示查询的执行方式,特别是使用哪些索引,并可能显示索引是期望的但不存在的位置。

我也发现在过去,NOT IN有时可能会非常慢。也许重写NOT IN作为NOT EXISTS可能会加快速度。

NOT EXISTS (SELECT * 
       FROM table_3 
       WHERE table_3.t3ID = table_1.ID AND 
         table_3.Col1 = '1') 
+0

更改NOT IN至NOT EXISTS似乎是相同的速度(无显着差异)。另外,我解释了查询,它主要返回NULL。 table_1正在读取1,500行以下,table_2正在读取超过7000行,其他2个表少于500行。除表名和选择类型以外的其他所有内容都是NULL。我尝试构建一个JOIN查询,它将拉动相同的数据,以查看它是否会更快,但似乎无法得到一个不会抛出错误并抓取相同数据的查询。感谢迄今为止的帮助! – Jay 2010-08-25 03:10:50

0

IDFMA

请邮寄以下脚本的结果,所以我们可以详细分析您的查询。如果你也可以pastebin结果,比如说http://pastie.org/,那也会很棒。

感谢

show create table table_1\G 
show indexes from table_1\G 

show create table table_2\G 
show indexes from table_2\G 

show create table table_3\G 
show indexes from table_3\G 

show create table table_4\G 
show indexes from table_4\G 

explain 
Select 
ID, Col1, Col2, Col3, Col4, Col5, Col6, Col7, 
Col8, Col9, Col10, Col11, Col12, Col13, Col14, Col15 
From 
table_1 
Where 
Active = '1' And 
Col2 LIKE '%Cat%' And Col3 <> 'blah' And Col3 <> 'blah1' And Col3 <> 'blah2' And Col3 <> 'blah3' And 
Col3 <> 'blah4' And Col3 <> 'blah5' And Col3 <> 'blah6' And 
ID Not In (Select t2ID From table_2 Where table_2.t2ID = table_1.ID And table_2.Col1 = '1' And table_2.Col2 = '1') And 
ID Not In (Select t3ID From table_3 Where table_3.t3ID = table_1.ID And table_3.Col1 = '1') And 
ID Not In (Select t4ID From table_4 Where table_4.t4ID = table_1.ID And table_4.Col1 = '1'); 
+0

此代码给出指向“show create table table_1 \ G”和“show table from table_1 \ G”的错误。 – Jay 2010-08-28 07:17:52

+0

这可能有助于http://pento.net/2009/02/27/the-g-modifier-in-the-mysql-command-line-client/ – 2010-08-28 07:40:58

+0

主帖已经被编辑并且有你要求的结果。 – Jay 2010-08-30 17:02:37

0

您可以分割该单个查询为多个独立的步骤,并使用临时表放在一个单一的存储过程。这将使它更具可读性,并可能运行得更快......

+0

这个查询每天会被成千上万的成员运行,这就是为什么首先需要优化的原因。我可能是错的,但不会将这个查询拆分成在数据库服务器上占用更多资源? – Jay 2010-08-28 07:27:24