我们正在使用以下问题从大型mysql表中获取日期。
SELECT fullPath, Permissiontype, DinstinguishedName
from cdm.test
where fullPath in
(SELECT distinct fullPath
FROMcdm.test
WHERE (Permissiontype = 'EXPLICIT' and not DinstinguishedName ='')
OR(Permissiontype = 'INHERITED'
AND (length(fullPath) - length(replace(fullPath,'/','')) < 4))
OR(Permissiontype = 'EXPLICIT'
AND NOT DinstinguishedName=''
AND LEFT(fullPath,length(fullPath)-Length(RIGHT(fullPath,INSTR(reverse(fullPath),'/'))))
AND(length(fullPath) - length(replace(fullPath,'/','')) > 2) ))
当我将需要显示的结果限制为270时,它运行得非常快,但是例如500行它不会运行。我在表中有1个77mil的行(需要在1个表中)。然后它运行了8个多小时仍然没有完成。有没有办法优化这个?
WKR。
答案 0 :(得分:1)
对于测试表中的每条记录,您将在子查询中再次查询整个表。不要在where子句中使用子查询,而是在同一个表上尝试内部联接。这将大大提高您的表现。
我还没有尝试过,但它可能看起来像:
SELECT fullPath, Permissiontype, DinstinguishedName from cdm.test
INNER JOIN (
SELECT distinct fullPath from cdm.test
where (Permissiontype = 'EXPLICIT' and not DinstinguishedName ='')
or (Permissiontype = 'INHERITED' AND (length(fullPath) - length(replace(fullPath,'/','')) < 4)) OR(Permissiontype = 'EXPLICIT'
AND NOT DinstinguishedName='' AND LEFT(fullPath,length(fullPath)-length(RIGHT(fullPath,INSTR(reverse(fullPath),'/'))))
and(length(fullPath) - length(replace(fullPath,'/','')) > 2) )
) AS SQ1
ON SQ1.fullpath = cdm.test.fullpath
答案 1 :(得分:0)
对于IN语句和子查询的组合,mysql有一个名为EXISTS()的有用优化器(不是专门用于此但可用于优化将子语句与子语句结合使用的查询)
根据https://dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists.html
的参考资料outer_expr IN (SELECT inner_expr FROM ... WHERE subquery_where)
与
相同 EXISTS (SELECT 1 FROM ... WHERE subquery_where AND outer_expr=inner_expr)
但更快
您的查询存在:
SELECT fullPath, Permissiontype, DinstinguishedName
FROM cdm.test cdm1
WHERE EXISTS(SELECT 0 FROM cdm.test cdm2 @wherecondition AND cdm2.fullPath = cdm1.fullPath)
@wherecondition =
WHERE (Permissiontype = 'EXPLICIT' and not DinstinguishedName ='')
OR(Permissiontype = 'INHERITED'
AND (length(fullPath) - length(replace(fullPath,'/','')) < 4))
OR(Permissiontype = 'EXPLICIT'
AND NOT DinstinguishedName=''
AND LEFT(fullPath,length(fullPath)-Length(RIGHT(fullPath,INSTR(reverse(fullPath),'/'))))
AND(length(fullPath) - length(replace(fullPath,'/','')) > 2))
答案 2 :(得分:0)
有几个问题会导致查询执行非常慢
您正在使用in
子句,但在很多情况下它们都很糟糕,所以最好将它们转换为JOIN子句。
即使使用JOIN,内部查询也有多个OR
条件,优化器也无法使用索引。
为什么你需要in clause
?
同一个查询可以写成
select fullPath,Permissiontype,DinstinguishedName from cdm.test
where
Permissiontype = 'EXPLICIT'
and not DinstinguishedName =''
union
select fullPath,Permissiontype,DinstinguishedName from cdm.test
where Permissiontype = 'INHERITED'
AND (length(fullPath) - length(replace(fullPath,'/','')) < 4)
union
select fullPath,Permissiontype,DinstinguishedName from cdm.test
where Permissiontype = 'EXPLICIT'
AND NOT DinstinguishedName=''
AND LEFT(fullPath,length(fullPath)-length(RIGHT(fullPath,INSTR(reverse(fullPath),'/'))))
and(length(fullPath) - length(replace(fullPath,'/','')) > 2)
请注意,我已将所有OR
条件更改为union
,这样会更快。
现在添加一个索引,如果它尚未添加为
alter table cdm.test add index search_data_idx(Permissiontype,DinstinguishedName,fullPath);