2011-10-13 54 views
1

我正在使用一些利用连接的MySQL语句。这些查询的性能似乎相当差,并且可能会在查询运行期间取消查询。下面列出的是我正在使用的查询的几个样本。我是MySQL JOIN语句的新手,对任何人都可以帮助我优化这些以获得更好的性能感到好奇。MySQL加入优化问题

我们使用这两种查询我们的售票系统数据库,生成有关处理各类门票的一些报道,他们从被处理的地点等

SELECT * FROM tickets t 
LEFT Join customfieldvalues cv1 ON t.ticketid = cv1.typeid 
LEFT Join customfields cf1 ON cv1.customfieldid = cf1.customfieldid 
LEFT Join customfieldoptions co1 on cv1.fieldvalue = co1.customfieldoptionid 
WHERE t.dateline BETWEEN 1314853200 AND 1317445199 
Group by t.ticketid 
Order by t.Dateline asc; 

这是一个基本的查询(无过滤添加)从9月1日至9月30日。运行时间〜140秒如果您拿走三条连接线,运行时间会缩短至约0.01秒。

SELECT * FROM tickets t 
LEFT Join customfieldvalues cv1 ON t.ticketid = cv1.typeid 
LEFT Join customfields cf1 ON cv1.customfieldid = cf1.customfieldid 
LEFT Join customfieldoptions co1 on cv1.fieldvalue = co1.customfieldoptionid 
LEFT Join customfieldvalues cv2 ON cv1.typeid = cv2.typeid 
LEFT Join customfields cf2 ON cv2.customfieldid = cf2.customfieldid 
LEFT Join customfieldoptions co2 on cv2.fieldvalue = co2.customfieldoptionid 
WHERE t.dateline BETWEEN 1314853200 AND 1317445199 
AND cf1.title ='Customer Type' AND co1.optionvalue = 'Staff' 
And cf2.title ='Building or Hall' AND co2.optionvalue like '%Stroupe%' 
Group by t.ticketid 
Order by t.Dateline asc; 

该查询将与2个过滤器基本查询补充说:客户类型(即员工)和地点建筑物或霍尔(Stroupe)。使用与上述相同的时间帧,运行时间约为0.1秒。

==============================

编辑:这里是EXPLAIN命令的输出上列出第一个查询。

INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','t','range','tickets7','tickets7','4',NULL,601,'Using where; Using temporary; Using filesort'); 
INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','cv1','ALL',NULL,NULL,NULL,NULL,104679,''); 
INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','cf1','eq_ref','PRIMARY','PRIMARY','4','DB.cv1.customfieldid',1,''); 
INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','co1','eq_ref','PRIMARY','PRIMARY','4','DB.cv1.fieldvalue',1,''); 

这是第二个查询的EXPLAIN输出。

1,SIMPLE,cf1,ref,“PRIMARY,title1”,title1,767,const,1使用where;其他;使用临时;使用filesort“1,SIMPLE,co1,ref,”PRIMARY,optionvalue1“,optionvalue1,767,const,1,”使用where“1,SIMPLE,cf2,ref,”PRIMARY,title1“,title1, 767,const,1,“使用where” 1,SIMPLE,tv,range,“PRIMARY,tickets7,tickets15,tickets16”,tickets7,4,NULL,601,“Using where”,SIMPLE,cv1,ref, customfieldvalues1,customfieldvalues1,8,“DB.cf1.customfieldid,DB.t.ticketid”,1,“Using where”,SIMPLE,cv2,ref,customfieldvalues1,customfieldvalues1,8,“DB.cf2.customfieldid,DB。 t.ticketid“,1,”Using where“,SIMPLE,co2,eq_ref,PRIMARY,PRI MARY,4,DB.cv2.fieldvalue,1,“使用哪里”

+0

您是否制作上参与JOIN操作的列索引? –

+0

@乔 - 我只是看着,是的,似乎每一个都有索引。 – John

+1

有两件事情可以帮助我们获得更好的答案:表格定义(所以我们可以检查我们预期的列上是否有索引)以及EXPLAIN –

回答

1

它的连接是错误的你的左连接+ where子句=内连接,你需要重写查询。

您的意思是让我把cf1中的所有行都放进去,即使它们不存在,也只有那些标题为'Customer Type'的行。

如果你改变了左侧连接到内部连接这将是更好的性能,(虽然可能不会返回你想要的)

+0

@凯文 - 感谢您的想法。我对此仍然陌生。我如何创建查询计划?另外,内部连接会更好吗?我已经为标题和选项值添加了两个索引(我认为我做对了)。 – John

+0

切换到内部联接对于数据库和where子句结合起来更有意义,在这两个部分冲突的时刻。 –

+0

是否有一个公式来理解连接类型。例如,你提到一个内部连接基本上是 - INNER JOIN = LEFT JOIN + WHERE CLAUSE?其他类型还有其他这样的公式吗? – John