SQL查询优化

时间:2013-01-27 01:38:55

标签: sqlite query-optimization

我正在尝试优化SQL查询。问题是它很慢!我正在使用sqlite和中型数据集(20000row)。我的sql语法如下所示:

SELECT DISTINCT date(A.last_update) as lastUpdate,
(SELECT COUNT(*) FROM bgp_update AS B WHERE date(B.last_update) = date(A.last_update) AND B.validity = 1) AS valid,
(SELECT COUNT(*) FROM bgp_update AS B WHERE date(B.last_update) = date(A.last_update) AND B.validity = 0) AS invalid,
(SELECT COUNT(*) FROM bgp_update AS B WHERE date(B.last_update) = date(A.last_update) AND B.validity = -1) AS notFound
FROM (SELECT DISTINCT last_update FROM bgp_update ORDER BY last_update) AS A WHERE last_update BETWEEN '%var' and '%var2';

以下是我的例子:

id   |     last_update   |  Validity

48   | 2009-1-6 18:34:38 |  notFound   
47   | 2009-1-6 18:34:38 |  valid   
46   | 2009-1-6 18:34:38 |  valid    
45   | 2009-1-3 18:34:38 |  invalid   
44   | 2009-1-3 18:34:38 |  invalid   
42   | 2009-1-4 18:34:38 |  notFound 
41   | 2009-1-4 18:34:38 |  notFound
48   | 2009-1-4 18:34:38 |  valid

查询结果如下:

    Date   |  valid   |  invalid   |    notFound

  2009-1-3 |   0      |     2      |       0
  2009-1-4 |   1      |     0      |       2
  2009-1-6 |   2      |     0      |       1

我需要这个来生成一个折线图。例如:line chart

但正如我提到的那样,查询非常慢!我怎样才能让它更快?

:::: 2.编辑:::::

之前的描述我简化了问题。我的表创建语句如下所示:

CREATE TABLE bgp_update
    (id INTEGER PRIMARY KEY,
    ip VARCHAR(64) NOT NULL,
    mask INTEGER NOT NULL,
    asn INTEGER NOT NULL,
    validity INTEGER NOT NULL,
    last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP)

如您所见,我的查询仅使用last_update和validity字段。

3 个答案:

答案 0 :(得分:2)

假设date函数可以理解proper format中的日期值,您可以简单地对要检查的条件求和(因为布尔表达式只返回0)或1):

SELECT date(last_update) AS Date,
       sum(validity = 'valid'   ) AS valid,
       sum(validity = 'invalid' ) AS invalid,
       sum(validity = 'notFound') AS notFound
FROM bgp_update
WHERE last_update BETWEEN ? AND ?
GROUP BY date(last_update)
ORDER BY date(last_update)

如果您在last_update列上有索引,则此查询效率很高,如果last_updatevalidity上有covering index,效率会更高一点}列。

答案 1 :(得分:1)

您可以对案例陈述使用总和,例如:

select last_update,
  sum(case when validity=1 then 1 else 0 end) valid,
  sum(case when validity=0 then 1 else 0 end) invalid,
  sum(case when validity=-1 then 1 else 0 end) notfound
from bgp_update
where last_update between '1/1/2013' and '1/2/2013'
group by last_update
order by last_update

SQL Fiddle

答案 2 :(得分:0)

嵌套子查询有时会使查询效率非常低。您可以考虑重写查询,以便它使用连接。

其次,您可以重新排列连接元素,其中具有最少记录的表最接近查询的开头。这样做会减少MySQL必须排序以从其他表中检索行的记录数。

此外,您可能需要考虑在ID列和具有您正在查看的特定值的表列上使用索引。

如果所有其他方法都失败了,您可能会发现三个单独的查询可能效率最高。