优化mySQL的SQL查询

时间:2012-02-21 14:23:13

标签: mysql sql

我刚刚从Access更改为mySQL。我有几张桌子,名为“Veranstaltung”和“Veranstaltung_User”。我希望得到用户所有的所有事件(= Veranstaltung),用户正在查看的那个事件。

我使用以下声明做了这个

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&gt; 5,table ware MyISAM)

感谢您的帮助

2 个答案:

答案 0 :(得分:2)

两个变化:
1.使用JOIN而不是嵌套的IN子句
2.使用<= and >代替YEAR()函数

改变1的优势在于,有时IN性能可能比预期的差,并且嵌套它们会使exascerabate。

更改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

答案 1 :(得分: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');

我还建议以下两个索引

CREATE INDEX dateIndex ON tbl_Veranstaltung (`Datum`);
CREATE INDEX userBewerIndex ON Veranstaltung_User (`BewerbID`,`UserID`);

之后,通过比较,查询应该是即时的

编辑如果我逐字地查看源查询,我会使用以下

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');