mySQL查询优化

时间:2014-05-17 22:39:32

标签: mysql

我正在努力优化这个SQL代码,有人可以帮忙吗?理想情况下,我需要输出完全相同的数据,以避免任何PHP编码。

我基本上希望能够按照设定范围对tariff_freemins进行分组。下面的代码有效,但运行时间超过2秒,对于网站来说,这个代码不够快。是否有优化的代码版本。该表有关于tariff_freemins设置的索引。

SELECT 'Free Mins' as category,
       'tariff_freemins' as fieldname, 
       t.range as `element`, 
       count(*) as phone_count 
from ( select deal_count, 
              case 
                when tariff_freemins between 0 and 200 then 'a0TO200' 
                when tariff_freemins between 200 and 400 then 'b200TO400' 
                when tariff_freemins between 400 and 600 then 'c400TO600' 
                when tariff_freemins between 600 and 1000 then 'd600TO1000' 
                when tariff_freemins between 1000 and 2000 then 'e1000TO2000'
                when tariff_freemins >2001 then 'hUnlimited' 
              end as `range` 
       from options
) t group by t.range

输出应如下所示:

"category"  "fieldname" "element"   "phone_count"
"Data Allowance"    "tariff_dataallowance"  "a0TO1" "289716"
"Data Allowance"    "tariff_dataallowance"  "b1TO2" "64472"
"Data Allowance"    "tariff_dataallowance"  "c2TO5" "114685"
"Data Allowance"    "tariff_dataallowance"  "d5TO11"    "33305"
"Data Allowance"    "tariff_dataallowance"  "e11TO20"   "36798"
"Data Allowance"    "tariff_dataallowance"  "f20TO50"   "5839"
"Data Allowance"    "tariff_dataallowance"  "hUnlimited"    "51114"

更新////////////////////

其次,我正在使用上面的许多mySQL查询来生成主表。每个都有单独的分组,并使用UNION ALL连接(见下文)。正如您所看到的那样,where子句指出“Where type ='Contract'”。我只能假设有一种方法可以通过查询在所有组中使用相同的筛选选项表?这看起来怎么样?有没有更好的方法来优化它?谢谢!

SELECT 'Phone Cost' as category,'offer_phonecost' as fieldname, offer_phonecost_range as `element`, count(*) as phone_count  from
options
WHERE 1  AND   type = 'Contract'   group by offer_phonecost_range UNION ALL 

SELECT 'Monthly Cost' as category,'offer_offerental' as fieldname, offer_offerental_range as `element`, count(*) as phone_count  from 
options
WHERE 1  AND   type = 'Contract'   GROUP BY offer_offerental_range UNION ALL 

SELECT 'Data Allowance' as category,'tariff_dataallowance' as fieldname, tariff_dataallowance_range as `element`, count(*) as phone_count  from 
options
WHERE 1  AND   type = 'Contract'   GROUP BY tariff_dataallowance_range

1 个答案:

答案 0 :(得分:1)

创建此索引:

create index opt_tariff on options( tariff_freemins );

并将查询重写为:

select 'Free Mins' as category,
       'tariff_freemins' as fieldname, 
        case 
                when tariff_freemins between 0 and 200 then 'a0TO200' 
                when tariff_freemins between 200 and 400 then 'b200TO400' 
                when tariff_freemins between 400 and 600 then 'c400TO600' 
                when tariff_freemins between 600 and 1000 then 'd600TO1000' 
                when tariff_freemins between 1000 and 2000 then 'e1000TO2000'
                when tariff_freemins >2001 then 'hUnlimited' 
        end as  `element`, 
        sum(cnt) as phone_count 
from (
      select  tariff_freemins, count(*) As cnt
      from options
      group by  tariff_freemins
) x
group by  element
;

内部子查询使用索引来优化GROUP BY,并且速度很快 外部查询无法优化 - 它不能在MySql中,因为MySql不支持基于表达式的索引 但是,外部查询在更小的数据集上执行聚合,这已经由内部子查询预先聚合,并且整个查询应该比您的版本更快。

使用基于表达式的索引,可以在其他RDBMS(如Oracle,PostgreSQL和SQL-Server)中轻松优化这样的查询。