在INNER JOIN上选择需要9个小时(并且计数)才能完成

时间:2015-11-24 12:47:50

标签: sql sqlite

我使用 sqlite数据库我从另一个脚本的输出中获取。我的查询需要花费大量时间才能完成。 samples表和multiclass表的相同~4,000,000 name多类表每个名称都有一行( 400万行),每个名称的样本表可以有一行或多行(> 1亿行)。我正在加入名称并汇总按tax_id,day和名称所属的样本分组的计数。 此查询应返回~25000行

以下是我使用的架构和查询的玩具版本:

SQL Fiddle

SQLite(SQL.js)架构设置

CREATE TABLE samples 
    (
     name varchar(20), 
     day integer, 
     sample integer,
     count integer
    );

CREATE TABLE multiclass 
    (
     name varchar(20), 
     tax_id varchar(20), 
     details varchar(30)
    );

INSERT INTO samples
(name, day, sample, count)
VALUES
('seq1', 204, 37, 50),
('seq2', 205, 37, 50),
('seq2', 206, 37, 50),
('seq3', 204, 37, 50),
('seq4', 205, 37, 50),
('seq4', 206, 37, 50);

INSERT INTO multiclass
(name, tax_id, details)
VALUES
('seq1', 'Vibrio', 'unimportant'),
('seq2', 'Shewenella', 'still_unimportant'),
('seq3', 'Vibrio', 'also_unimportant'),
('seq4', 'Shewenella', 'doesntmatter');

查询1

SELECT tax_id, day, sample, SUM(count) 
FROM samples INNER JOIN multiclass USING(name) 
GROUP BY tax_id, day, sample 
ORDER BY day, sample;

Results

|     tax_id | day | sample | SUM(count) |
|------------|-----|--------|------------|
|     Vibrio | 204 |     37 |        100 |
| Shewenella | 205 |     37 |        100 |
| Shewenella | 206 |     37 |        100 |

我是SQL新手,不知道如何继续。这是一个我只需要执行一次的查询。所以我不确定在表中添加索引是否合适。

是否有不同的方法来构建查询以使其运行得更快?添加索引是否有意义或需要太长时间?如果花了9个小时,它是否仍然可能挂在SQL上,或者出现其他问题?

修改更新了问题以包含数据库架构和预期结果。我目前正在samples.name列上构建索引,它已经运行了4个多小时(在群集环境中使用60 Gigs ram和许多cpus的节点)。

2 个答案:

答案 0 :(得分:1)

此查询:

SELECT tax_id, day, sample, SUM(count) 
FROM samples INNER JOIN
     multiclass
     ON samples.name = multiclass.name 
GROUP BY tax_id, day, sample 
ORDER BY day, sample;

非常简单。通常建议使用samples(name)multiclass(name)的索引。

但是,您的问题中有一个提示,即两个表都包含400万行,但您只需要25,000行。我怀疑你在每张表中都有重复的名字。要确定join生成的中间行数,请运行以下查询:

select sum(s.cnt * m.cnt), max(s.cnt * m.cnt)
from (select name, count(*) as cnt from samples group by name
     ) s join
     (select name, count(*) as cnt from multiclass group by name
     ) m
     on s.name = m.name;

我猜你会得到一个非常大的数字,解释为什么查询花了这么长时间。

不幸的是,在这一点上,我没有关于如何解决问题的真实答案,因为您的问题没有指定您实际想要查询生成的内容。但是,在加入表之前聚合表可能是一种可能的解决方案。

答案 1 :(得分:0)

问题是我正在使用的群集上安装的sqlite3版本。群集上的版本是3.6.20。这似乎令人难以置信,但是从sqlite网站下载了3.9.2的二进制文件,并在不到10分钟的时间内完成了完全相同的查询。