2012-02-21 88 views
2

我刚刚从Access更改为mySQL。我有几张桌子叫做“Veranstaltung”和“Veranstaltung_User”。我想要获取用户所收到的所有事件(= Veranstaltung),免除用户正在查看的事件。为mySQL优化SQL查询

我这样做有以下statment

SELECT VID, Bezeichnung, Datum 
FROM tbl_Veranstaltung 
WHERE year(Datum) = 2012 
    AND VID <> 613 
    AND VID IN (SELECT BewerbID 
       FROM Veranstaltung_User 
       WHERE UserID IN (SELECT UserID 
           FROM Veranstaltung_User 
           WHERE BewerbID = 613) 
        AND UserID <> 0) 
ORDER BY Datum 

在Access中,这个查询是相当快 - 在MySQL的需要44,56秒 - 太;-)

如何优化我的声明加快查询? (mySQL的> 5,表洁具的MyISAM)

感谢帮助

回答

2

两个更改:
1.用途的JOIN代替嵌套IN子句
2.采用的<= and >代替YEAR()功能

的变化1的优势在于,有时候IN性能可能会比预期的差,并且嵌套它们将会超出这一点。

变化2的优点是它允许索引查找找到一系列记录。在哪里使用YEAR()来扫描整个表/索引。

两者都假定您有适当的索引。

SELECT 
    V.VID, V.Bezeichnung, V.Datum 
FROM 
    tbl_Veranstaltung  V 
INNER JOIN 
    Veranstaltung_User VUser 
    ON VUser.BewerbID = V.VID 
INNER JOIN 
    Veranstaltung_User VUser2 
    VUser.UserID = VUser2.UserID 
WHERE 
     V.Datum >= '20120101' 
    AND V.Datum < '20130101' 
    AND V.VID <> 613 
    AND VUser.UserID <> 0 
    AND VUser2.BewerbID = 613 
ORDER BY 
    Datum 
+0

你错过在内的“上”加入 - 但它工作;-) – Stefan 2012-02-21 15:01:39

+0

@Stefan - 尼斯点:) – MatBailie 2012-02-21 15:16:21

0

该查询可能需要调整,试图作出一些假设以表格布局+将更新基础上提供

SELECT 
    v.VID, 
    v.Bezeichnung, 
    v.Datum 

FROM tbl_Veranstaltung AS v 

INNER JOIN Veranstaltung_User AS vu 
ON vu.BewerbID = v.VID 
AND vu.UserID = [THIS USER ID] 
AND vu.BewerbID <> 613 

// Used a BETWEEN so that MySQL does not need to apply YEAR() to every row 
WHERE v.Datum BETWEEN DATE('2012-01-01') AND DATE('2012-12-30'); 

我也建议以下两个指标任何澄清

​​

之后,查询应该几乎是即时比较

编辑如果我参加了源查询逐字我会用以下

SELECT 
    v.VID, 
    v.Bezeichnung, 
    v.Datum 

FROM tbl_Veranstaltung AS v 

INNER JOIN Veranstaltung_User AS vu 
ON vu.BewerbID = v.VID 
AND vu.BewerbID <> 613 
AND vu.UserID <> 0 

WHERE v.Datum BETWEEN DATE('2012-01-01') AND DATE('2012-12-30');