MySQL 连接优化问题
我正在处理一些利用连接的 MySQL 语句。这些查询的性能似乎相当差,并且可能会在查询运行期间降低性能。下面列出了我正在使用的查询的几个示例。我是 MySQL JOIN 语句的新手,很好奇是否有人可以帮助我优化这些语句以获得更好的性能。
我们使用这两者来查询我们的票务系统数据库,以生成一些有关处理的票证类型、处理票证的位置等的报告。
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 的输出。
id、select_type、表、类型、possible_keys、键、key_len、ref、行、额外 1,SIMPLE,cf1,ref,"PRIMARY,title1",title1,767,const,1,"使用where;使用临时;使用文件排序" 1,SIMPLE,co1,ref,"PRIMARY,optionvalue1",optionvalue1,767,const,1,"使用位置" 1,SIMPLE,cf2,ref,"PRIMARY,title1",title1,767,const,1,"使用位置" 1,SIMPLE,t,range,"PRIMARY,tickets7,tickets15,tickets16",tickets7,4,NULL,601,"使用位置" 1,SIMPLE,cv1,ref,customfieldvalues1,customfieldvalues1,8,"DB.cf1.customfieldid,DB.t.ticketid",1,"使用位置" 1,SIMPLE,cv2,ref,customfieldvalues1,customfieldvalues1,8,"DB.cf2.customfieldid,DB.t.ticketid",1,"使用位置" 1,SIMPLE,co2,eq_ref,PRIMARY,PRIMARY,4,DB.cv2.fieldvalue,1,"使用位置"
I am working with some MySQL statements that utilize joins. The performance for these queries seems to be rather poor and can take down the during the time in which the query is running. Listed below are a couple samples of the queries that I am using. I am new to MySQL JOIN statements and was curious if anyone could help me in optimizing these for better performance.
We use both of these to query our ticketing system database to generate some reports about the types of tickets handled, the location they were handled from, etc.
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;
This one is the basic query (no filtering added) from Sep 1st to Sep 30th. Runtime ~140 sec. If you take away the three join lines, the run time is cut down to ~0.01 sec.
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;
This query would be the basic query with 2 filters added: customer type (i.e. Staff) and the location Building or Hall (Stroupe). Using the same time frame as the one above, the run time is ~0.1 sec.
==============================
EDIT: Here is the output of the EXPLAIN command on the first query listed.
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,'');
Here is the output of EXPLAIN from the second query.
id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1,SIMPLE,cf1,ref,"PRIMARY,title1",title1,767,const,1,"Using where; Using temporary; Using filesort"
1,SIMPLE,co1,ref,"PRIMARY,optionvalue1",optionvalue1,767,const,1,"Using where"
1,SIMPLE,cf2,ref,"PRIMARY,title1",title1,767,const,1,"Using where"
1,SIMPLE,t,range,"PRIMARY,tickets7,tickets15,tickets16",tickets7,4,NULL,601,"Using where"
1,SIMPLE,cv1,ref,customfieldvalues1,customfieldvalues1,8,"DB.cf1.customfieldid,DB.t.ticketid",1,"Using where"
1,SIMPLE,cv2,ref,customfieldvalues1,customfieldvalues1,8,"DB.cf2.customfieldid,DB.t.ticketid",1,"Using where"
1,SIMPLE,co2,eq_ref,PRIMARY,PRIMARY,4,DB.cv2.fieldvalue,1,"Using where"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
它的连接是错误的,你的左连接+where子句=内连接,你需要重写查询。
您是说从 cf1 获取所有行,即使它们不存在,并且只获取标题为“客户类型”的行。
如果您将左连接更改为内连接,它将提高性能(尽管可能不会返回您想要的结果)
Its the joins that are wrong your left join + where clause = inner join, you need to rewrite the query.
You are saying get me all of the rows from cf1 even if they do not exist and only the ones that have a title of 'Customer Type'.
If you change the left joins to inner joins it will be more performant, (although may not return what you want)