提高查询的性能以删除重复项

Posted

技术标签:

【中文标题】提高查询的性能以删除重复项【英文标题】:Improve performance for query to delete duplicates 【发布时间】:2013-04-01 16:47:34 【问题描述】:

我的托管公司最近从慢查询日志中给了我这个条目。检查的行似乎过多,可能有助于降低服务器的速度。 phpMyAdmin 中的测试导致持续时间为 0.9468 秒。

Check_in 表通常包含 10,000 到 17,000 行。它还有一个索引:Num, unique = yes, cardinality = 10852, collat​​ion = A.

我想改进这个查询。 WHERE 后面的前五个条件包含要检查以排除重复项的字段。

# User@Host: fxxxxx_member[fxxxxx_member] @ localhost []
# Query_time: 5  Lock_time: 0  Rows_sent: 0  Rows_examined: 701321
use fxxxxx_flifo;
SET timestamp=1364277847;
DELETE FROM Check_in USING Check_in, 
Check_in as vtable WHERE 
    ( Check_in.empNum = vtable.empNum ) 
AND ( Check_in.depCity = vtable.depCity ) 
AND ( Check_in.travelerName = vtable.travelerName ) 
AND ( Check_in.depTime = vtable.depTime ) 
AND ( Check_in.fltNum = vtable.fltNum ) 
AND ( Check_in.Num > vtable.Num ) 
AND ( Check_in.accomp = 'NO' ) 
AND Check_in.depTime >= TIMESTAMPADD ( MINUTE, 3, NOW() )
AND Check_in.depTime < TIMESTAMPADD ( HOUR, 26, NOW() );

编辑:

empNum int (6) 姓氏 varchar (30) travelerName varchar (40) (99.9% = 'All') depTime 日期时间 fltNum varchar (6) depCity varchar (4) 总共 23 个字段(包括一个 blob,包含 25K 图像)

编辑:

ADD INDEX deleteQuery (empNum, lastName, travelerName, depTime, fltNum, depCity, Num)

这是创建索引的问题吗?如果有,是什么类型,什么字段?

最后 3 个条件通过询问是否完成以及在时间段内来限制行数。他们能否在查询中(更早)更好地定位?第5个AND ...有必要吗?

接受所有想法。感谢观看。

【问题讨论】:

我建议您检查执行计划:explain select ...(而不是删除)。在那里你可以检查你可能需要索引的字段。 @Barranka 你能解释一下吗?我还不了解索引。你是建议explain select * from Check_in 还是explain Num, empNum, depCity ... 【参考方案1】:

如果不查看表定义,很难确切知道如何提供帮助。

不要删除自联接(两次提到的同一个表),因为此查询正在清除重复项 (check_in.Num &gt; vtable.Num)。

你有关于 depTime 的索引吗?如果没有,请添加一个。

您可能还想在

上添加复合索引
 (empNum,depCity,travelerName,depTime,fltNum)

优化自连接。您可能需要花点时间才能弄清楚什么是有效的。

【讨论】:

在5加Num上加上index后,查询确实提速了。例如,现在以 0.0228 运行。这可能是“简单”的把戏。我会被阅读 -> How mysql uses Indexes 'muck about' 听起来像是技术性很强的建议。 :) deptime,empNum,depCity,travelerName,fltNum 上的单个索引(NB deptime first)将执行 Ollie 提出的 2 个索引的功能,同时减少插入/更新/删除的开销。跨度> 顺便说一句:胡闹是优化系统的一种行之有效的做法。但是,当您付钱请人这样做时,他们会使用“增量路径优化”、“目标搜索”和“避免局部最小值”等术语来描述它【参考方案2】:

如果您的目标是删除重复项,则解决方案是首先避免出现重复项 - 在您认为共同定义重复项的字段中定义一个唯一索引(但您将无法创建索引,而您在数据库中有重复项)。

this 查询所需的索引为 (deptime,empnum,depcity,travellername,fltnum,num,accomp 按此顺序。deptime 字段必须首先让它优化表上的 2 个访问。删除重复项后,使索引唯一。

暂且不说,您会遇到一大堆性能问题。

1) 您似乎在提供某种商业服务 - 那么您为什么要等待您的 ISP 告诉您您的网站正在像狗一样运行?

2) 虽然您的索引应设计为防止重复,但在许多情况下其他索引将有助于提高性能 - 但为了了解这些索引是什么,您需要查看针对您的数据运行的所有查询。

3) blob 可能应该在单独的表中

他们能否在查询中(更早)更好地定位?

查询层次结构中同一级别的谓词顺序对性能没有影响。

第五个 AND 有必要吗?

如果您的意思是“AND (Check_in.Num > vtable.Num)”,那么是的 - 否则它将删除 all 重复的行 - 即它不会留下一行.

【讨论】:

第二段和关于 blob 的优秀建议。不是每个人都开始使用所有知识进行编程。有很多东西要学。嘿,我什至赞赏第 3 段。问题一一解决。 您建议的索引似乎已将查询时间从 0.02 减少到 0.002。【参考方案3】:

索引的目的是加快搜索和过滤速度...索引(用外行术语来说)是一个排序表,它精确定位数据的每一行(可能本身是未排序的)。

因此,如果您想加快删除查询的速度,了解数据的位置会有所帮助。因此,作为一组经验法则,您需要为以下字段添加索引:

    每个主键或外键 您执行频繁搜索/过滤的每个日期 您执行频繁搜索/过滤的每个数字字段

我避免对文本字段进行索引,因为它们非常昂贵(就空间而言),但是如果您需要对文本字段执行频繁的搜索,您也应该对它们进行索引。

【讨论】:

请参阅编辑数据类型和添加索引。在 7 个项目上添加索引是正确的答案吗(6 个项目符号和 Num(已经唯一)??对于您对文本字段的评论,我的 varchars 是否足够小?您对索引有什么建议?

以上是关于提高查询的性能以删除重复项的主要内容,如果未能解决你的问题,请参考以下文章

如何删除 MySQL 表中的重复项

查询删除重复项

PDO:删除查询结果的重复项[重复]

用于计算重复项的 SQL 查询 [重复]

如何删除使用 array_agg postgres 函数生成的重复项

从 SQLite 中的 SQL 查询结果中删除重复项