2013-04-29 80 views
0

我目前有一个SQL查询需要很长的时间来加载,想知道如果有人可以帮我吗?我对MySQL相当陌生。使SQL查询更快

这是查询:

SELECT applicationid 
FROM logs 
WHERE action = 'VIEWED' 
AND userid = '$user' 
AND date >= '$dateminus7' 
AND applicationid NOT IN (
    SELECT applicationid 
    FROM logs 
    WHERE userid = '$user' 
    AND date >= '$dateminus7' 
    AND (action LIKE 'SUBMITTED NOTE%' OR action LIKE 'CHANGED STATUS%') 
) 

基本上翻翻某些数据库发现,不会离开笔记,当他们访问客户的账户(很调皮)的用户。日志数据库中每周有大约30,000条记录,这显然是一个因素,但现在查询运行了一个小时,仍然没有完成(超时,PHP页面上的404错误)。任何信息只需要问,我会很感激任何提示或指针。

编辑:EXPLAIN结果http://i.imgur.com/h9bZBe3.png

+1

您是否在表格中添加了索引 – Satya 2013-04-29 15:31:35

+2

我们需要看到一个'EXPLAIN'语句。 – Kermit 2013-04-29 15:41:58

+0

原谅我,什么是EXPLAIN语句? – MikeK 2013-04-29 15:53:36

回答

1

(userid, date)的复合指数应足以在这里加快这两个查询。您也可以尝试(userid, date, action)(action, userid, date)。根据哪个列有更多的唯一值,一个索引可能比另一个索引更有效。

请注意,查询规划器可能无法优化子查询,并且它可能会为外部查询中的每个候选行执行一次子查询。多次运行内部查询的成本可能会导致性能问题。考虑尝试代替连接,看看你获得更好的性能:

SELECT la.applicationid 
FROM logs la 

LEFT OUTER JOIN logs lb 
    ON la.applicationid = lb.applicationid 
    AND lb.userid = '$user' 
    AND lb.date >= '$dateminus7' 
    AND (lb.action LIKE 'SUBMITTED NOTE%' OR lb.action LIKE 'CHANGED STATUS%') 

WHERE la.action = 'VIEWED' 
AND la.userid = '$user' 
AND la.date >= '$dateminus7' 
AND lb.applicationid IS NULL; 
+0

这与用户Barmar的回答非常接近,所以听起来很有希望,但正如我对他说的,没有结果返回,只有一个SQL错误:'未知表状态:TABLE_TYPE'。我的'日期'字段的类型是'日期',这是一个问题吗?我开始认为这可能是因为我发现日期值之外的结果(我在OP中使用原始语句时)。 – MikeK 2013-04-29 15:55:46

+0

该错误似乎是一个phpmyadmin错误。请参阅http://stackoverflow.com/questions/2955097/information-schema-shows-unknown-table-status-table-type-mysql-phpmyadmin – Barmar 2013-04-29 16:03:34

0

我发现,MySQL不优化INNOT IN查询非常好。用JOIN替换它们通常会改善事情。对于NOT IN你必须使用一个LEFT OUTER JOIN

SELECT l1.applicationid 
FROM logs l1 
LEFT OUTER JOIN (SELECT applicationid 
    FROM logs 
    WHERE userid = '$user' 
    AND date >= '$dateminus7' 
    AND (action LIKE 'SUBMITTED NOTE%' OR action LIKE 'CHANGED STATUS%')) l2 
ON l1.applicationid = l2.applicationid 
WHERE l1.action = 'VIEWED' 
AND l1.userid = '$user' 
AND l1.date >= '$dateminus7' 
AND l2.applicationid IS NULL 
+0

这不会返回任何结果,无论我投入什么日期,但它似乎很快就完成了。一个问题,我的'日期'字段是'日期'类型,这是一个问题吗?我开始认为这可能是因为我看到的结果超出了我期望回归的日期值。 – MikeK 2013-04-29 15:51:30

+0

您是否使用小型测试表测试过您的查询以确保其正常工作?我认为我的查询与你的相同。由于您的查询从未完成,您如何知道它会返回结果?你可以在sqlfiddle.com上发布一个小样本的数据吗? – Barmar 2013-04-29 15:54:59

+0

它确实会返回结果,它只需要非常非常长的时间,远远超过实际。最终查询超时,但之前(在我的php页面)上半年的用户出现了一些结果。 – MikeK 2013-04-29 15:57:01

0

你有两个“行动=‘XXX’”两个querys(主之一,子查询),他们难道没有有共同点,我认为任何记录。 换句话说,如果您正在寻找一些“VIEWED”操作的应用程序。你不需要使用查询:

SELECT的applicationID 原木 其中userid = '$用户' 和日期> = '$ dateminus7' AND(动作LIKE '提交注%' 或行动LIKE“的状态已改变%')

不知道我是否遗漏了一些东西,这是否会有所帮助。我会遵循这一点。

+0

我首先需要找到每个applicationid,一个用户'查看',然后我需要看看,如果applicationid是在子查询。子查询正在检查相同的用户是否留下了一个音符(当用户离开音符时出现另外两个动作条件)。如果在子查询中找不到applicationid,则不会留下任何注释,这就是我需要的信息。 – MikeK 2013-04-29 15:44:20

+0

@ user2332653 Thx for clearfying。我想我得到了你想要做的。但是让我困惑的是,你的意思是表单日志中的一个applicationid可能同时有两个动作吗?比如“VIEWED”和“'提交注'%”“ – PngL 2013-04-29 15:57:53

+0

是的,但它们在数据库中会显示为单独的条目(单独记录用户操作)。当用户查看某些信息时,它会记录下来,当他们记下为什么他们查看了这些信息并记录下来时,我基本上正在做的是试图确保查看应用程序的用户也记录了他们查看它的原因。 – MikeK 2013-04-29 15:59:48