2

我正在尝试优化 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

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

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

:::: 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 和有效性字段。

4

3 回答 3

3

假设日期值采用函数可以理解的正确格式date,您可以简单地将要检查的条件相加(因为布尔表达式只返回 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如果您在列上有索引,则此查询将很有效,如果您在and列上有覆盖索引,则效率更高。last_updatevalidity

于 2013-01-27T11:53:55.330 回答
2

您可以使用 sum over case 语句,例如:

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小提琴

于 2013-01-27T03:05:55.273 回答
0

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

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

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

如果一切都失败了,您可能会发现三个单独的查询可能是最有效的。

于 2013-01-27T02:48:44.330 回答