优化MySQL报表查询

时间:2017-01-28 13:03:40

标签: php mysql

我有一些查询需要花费30多分钟来执行,我不是数据库专家,所以我真的不知道这里有什么,我需要有人建议更好的查询:

select count(*),substring(tdate,1,7) 
from bills 
where amt='30' 
group by substring(tdate,1,7) 
order by substring(tdate,1,7) desc

SELECT count(*) 
FROM `bills` 
where amt='30' 
and date(tdate)=date('$date') 
and stat='RENEW' 
and x1 in (select `id` from sub); 

这里我以下列格式传递$ date的值' Y-m-d 00:00:00'

select count(*),substring(tdate,1,7) 
from bills 
where amt='30' 
group by substring(tdate,1,7) 
order by substring(tdate,1,7) desc

表格结构:

MariaDB [talksport]> desc bills;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| bid   | int(11)      | NO   | PRI | NULL    | auto_increment |
| num   | varchar(500) | NO   |     | NULL    |                |
| stat  | varchar(500) | NO   |     | NULL    |                |
| tdate | varchar(500) | NO   |     | NULL    |                |
| x1    | varchar(500) | NO   |     | NULL    |                |
| amt   | varchar(500) | NO   |     | 30      |                |
+-------+--------------+------+-----+---------+----------------+

欢迎任何和所有帮助。

迈克尔

2 个答案:

答案 0 :(得分:1)

你的三个查询真的是两个(第一个和第三个是相同的)。这些是你的三个查询(重新格式化,因此它们是可读的):

select count(*), left(tdate, 7)
from bills
where amt = '30'
group by left(tdate, 7)
order by left(tdate, 7) desc;

select count(*)
from `bills`
where amt = '30' and date(tdate) = date('$date') and stat = 'RENEW' and
      x1 in (select `id` from sub);

首先,您希望第一个查询的bills(amt, tdate)上有索引。第二个问题更多。在某些版本的MySQL中,in可能是个问题。此外,日期算术也存在问题。因此,如果您将tdate存储为YYYY-MM-DD,则以相同的格式传递$date(更好的是,使用参数,更好,但使用正确的类型)。所以,我会把它写成:

select count(*)
from `bills` b
where amt = '30' and tdate = '$date' and stat = 'RENEW' and
      exists (select 1 from sub s where b.x1 = s.id);

然后你需要bills(amt, stat, tdate, id)上的索引。

正确的索引可以加快您的查询速度。

答案 1 :(得分:0)

除了上面的答案之外,可以做的另一项优化是将COUNT(*)替换为COUNT(id)

当您计算所有行并且每行都有一个唯一标识符(idPRIMARY KEY,已经编入索引)时,您也可以获得相同的COUNT如果你只统计了ids。查询将不得不查找较少数量的列以及将要筛选的列已经编入索引以使搜索和聚合更快。

*查询中尝试使用特定列名而不是SELECT总是好的。同样,请始终查看SELECT中使用的列以及参与WHEREGROUP BY子句的列,以确定潜在的索引候选对象。


请注意:
不应该假设创建多个索引是唯一的优化方法,因为它可能会减慢批量INSERT s / UPDATE,同时尝试显着加快SELECT。此外,您最终可能会创建可能变得多余或冗余的索引。因此,必须考虑应用程序目的的整体观点以获得最佳平衡 - 取决于更多用户操作是否集中在INSERT / UPDATESELECT