哪些点使SQL查询更快

时间:2018-01-07 11:28:00

标签: mysql sql query-performance

我是SQL代码的新手,我只选择几列并使用大多数GROUP BY函数,但我的代码需要2分钟才能显示结果可能不是很长的查询,但我需要更快。如何更快地进行SQL查询?

对于我的代码,我有一个联赛匹配的表格;

实施例

CustomerID        MatchDate         League              Matches                HomeTeam                AwayTeam
------------------------------------------------------------------------------------------------------------------------
1                 11-12-2006        La Liga             Barcelone-R.Madrid     Barcelona               RealMadrid
2                 10-10-2006        Premier League      Everton-Arsenal        Everton                 Arsenal
3                 09-10-2006        Premier League      Arsenal-Tottenham      Barcelona               RealMadrid
4                 10-10-2006        Bundesliga          Bayern-Mainz           Bayern                  MainZ 

我的目标是,计算每个比赛的总ID,以便HomeTeam和AwayTeam为联盟和球队和季节找到每个球队和小组的总观察数。 同样的团队可以是HomeTeam和AwayTeam,所以我使用了这段代码。

SELECT League, SUM(totalnum), Teams, Season FROM 
    (
        (SELECT DATE_FORMAT(MatchDate, '%Y') as 'Season', HomeTeam as Teams, League, count(distinct CustomerID) as "totalnum" 
            FROM MY_TABLE GROUP BY League, Teams, Season ) 
        UNION ALL 
        (SELECT DATE_FORMAT(MatchDate, '%Y') as 'Season', AwayTeam as Teams, League, count(distinct CustomerID) as "totalnum" 
            FROM MY_TABLE GROUP BY League, Teams, Season )
    ) aa
GROUP BY League, Teams, Season
ORDER BY totalnum DESC

我可以得到结果,但我需要更短。哪些点可能会影响我的查询。

2 个答案:

答案 0 :(得分:2)

如果你应用这两个索引,我希望你现有的查询应该加快......

CREATE INDEX MY_TABLE_league_home_date_cust
    ON MY_TABLE(
        League, HomeTeam, MatchDate, CustomerID
    );

CREATE INDEX MY_TABLE_league_away_date_cust
    ON MY_TABLE(
        League, AwayTeam, MatchDate, CustomerID
    );


尽管如此,我怀疑您的查询所涉及的最高费用是COUNT(DISTINCT CustomerID)。这样做涉及必须对所有数据进行排序。这个可能意味着以下索引可能更好......

CREATE INDEX MY_TABLE_cust_league_home_date
    ON MY_TABLE(
        CustomerID, League, HomeTeam, MatchDate
    );

CREATE INDEX MY_TABLE_cust_league_away_date
    ON MY_TABLE(
        CustomerID, League, AwayTeam, MatchDate
    );


另一个观察结果是,在您的查询中,您COUNT()独特的"家庭客户"然后COUNT()独特的"客户",然后SUM()他们。这意味着任何去过主场比赛和客场比赛的人都会计算两次。那是为了吗?

如果不是这样,您可能会发现查询的费用更高......

SELECT
  Team,
  League,
  DATE_FORMAT(MatchDate, '%Y')   AS Season,
  COUNT(DISTINCT CustomerID)     AS total
FROM 
(
  SELECT CustomerID, League, HomeTeam AS Team, MatchDate FROM MyTable
  UNION ALL
  SELECT CustomerID, League, AwayTeam AS Team, MatchDate FROM MyTable
)
  combined_view
GROUP BY
  Team, League, Season
ORDER BY
  total DESC


我认为你最好的选择是为Season添加一个计算列,然后使用第一个索引的略微修改版本......

ALTER TABLE
  MY_TABLE
ADD Season VARCHAR(4) AS (
  DATE_FORMAT(MatchDate, '%Y')
);

CREATE INDEX MY_TABLE_league_home_season_cust
    ON MY_TABLE(
        League, HomeTeam, Season, CustomerID
    );

CREATE INDEX MY_TABLE_league_away_season_cust
    ON MY_TABLE(
        League, AwayTeam, Season, CustomerID
    );

SELECT
  Team,
  League,
  Season,
  COUNT(DISTINCT CustomerID)     AS total
FROM 
(
  SELECT CustomerID, League, HomeTeam AS Team, Season FROM MyTable
  UNION ALL
  SELECT CustomerID, League, AwayTeam AS Team, Season FROM MyTable
)
  combined_view
GROUP BY
  Team, League, Season
ORDER BY
  total DESC

答案 1 :(得分:1)

你能试试吗?

SELECT DATE_FORMAT(A.MatchDate, '%Y') as 'Season',  
       case c.col
         when 'home' then A.HomeTeam
         when 'away' then A.AwayTeam
       end as Teams,
       A.League, count(distinct A.CustomerID) as "totalnum" 
        FROM MY_TABLE A
        cross join ( select 'home' as col union all select 'away') c
     GROUP BY League, Teams, Season
ORDER BY totalnum DESC

在SQL Fiddle中查看结果:new:http://sqlfiddle.com/#!9/dd0335/11(上一个:http://sqlfiddle.com/#!9/dd0335/9