SQL语句需要花费大量时间,是否可以对其进行优化?

时间:2014-07-23 11:20:12

标签: java sql sqlite

这是我的SQL查询,我得到了所有重复项,但是一个(最新的):

SELECT d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID, d.C_DateCreated 
FROM duplicates as d 
WHERE d.C_DateCreated !=(select max(d2.C_DateCreated) 
FROM duplicates d2 
WHERE d2.C_DataSourceId = d.C_DataSourceId)

有可能以某种方式优化它吗?不幸的是,在30万条记录中需要花费+ - 40分钟。

查询的方法是:

public ArrayList<Record> get() throws SQLException,
        ClassNotFoundException {
    Statement st = DBConnect.DBC.con.createStatement();
    String sql = ("select d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID, 
d.C_DateCreated "
            + "from duplicates as d "
            + "where d.C_DateCreated !=(select max(d2.C_DateCreated) "
            + "from duplicates d2 where d2.C_DataSourceId = d.C_DataSourceId)");
    ResultSet rs = st.executeQuery(sql);
    DBConnect.DBC.con.commit();
    while (rs.next()) {

        int contactID = rs.getInt("C_ContactID");
        String email = rs.getString("C_EmailAddress");
        String dataSourceID = rs.getString("C_DataSourceID");
        String dateCreated = rs.getString("C_DateCreated");
        duplicate = new Record(contactID, email, dataSourceID, dateCreated);
        duplicates.add(duplicate);
    }
    rs.close();
    st.close();

    return duplicates;
}

3 个答案:

答案 0 :(得分:2)

首先要在duplicates(C_DataSourceId, C_DateCreated)上创建一个索引:

create index duplicates_DataSourceId_DateCreated on duplicates(C_DataSourceId, C_DateCreated);

如果您使用的是支持窗口函数的数据库,那么我将其改为:

SELECT d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID, d.C_DateCreated 
FROM (select d.*, max(C_DateCreated) over (partition by C_DataSourceId) as maxdc
      from duplicates d 
     ) d
WHERE d.C_DateCreated <> maxdc;

值得进行比较,因为有时候窗口函数有效实现。

而且,如果您有索引,则查询的效率稍高一点:

SELECT d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID, d.C_DateCreated 
FROM duplicates d
WHERE EXISTS (select 1
              from duplicates 2
              where d2.C_DataSourceId = d.C_DataSourceId and
                    d2.C_DateCreated > d.C_DateCreated
             );

这表示从重复项中获取所有行,其中有另一行(具有相同的源)创建了更大的日期。一个小小的优点是,它不必查看所有值来获取max()。它只需要找到第一个。主要的性能改进将是综合指数。

答案 1 :(得分:1)

为列C_DateCreated和C_DataSourceId创建索引。这将减少执行查询的时间。请参阅此链接以了解如何创建索引。  http://www.tutorialspoint.com/mysql/mysql-indexes.htm

答案 2 :(得分:0)

在T-SQL中,答案看起来像这样,但我认为SQLite不支持窗口函数(尽管后代的答案完好无损):

你可以使用一个窗口函数用它在公共C_DataSourceIDs组中的位置标记每一行,然后用CTE选择那些不在位置1的行。

with ordered as (
    select
        d.C_ContactID,
        d.C_EmailAddress,
        d.C_DataSourceID,
        d.C_DateCreated,
        row_number() over (
            partition by
                d.C_DataSourceID
            order by
                d.C_DateCreated
        ) as rownum
    from
        duplicates
) select
    C_ContactID,
    C_EmailAddress,
    C_DataSourceID,
    C_DateCreated
from
    ordered
where
    rownum != 1;

使用(C_DataSourceID, C_DateCreated)上的索引,只需要对表进行一次传递,而不是查询中的自联接。