在大型数据集上使用PostgreSQL进行特征工程(~3M条目)

时间:2016-08-19 18:24:11

标签: python sql postgresql machine-learning bigdata

我有大约300万个国际象棋游戏的数据集(现有列包括玩家名称,日期,结果和锦标赛名称)。我想用随机森林来预测国际象棋比赛的结果。

为此,我想做一些特色工程。我认为有几个变量是强有力的预测因子,例如:玩家'到目前为止比赛结果,比赛前90天比赛的数量。

专栏:

 - date DATE  
 - namew TEXT  
 - nameb TEXT  
 - whiterank INTEGER  
 - blackrank INTEGER  
 - tournament TEXT  
 - t_round INTEGER  
 - result REAL  
 - id BIGINT  
 - chess_data2_pkey(id)

指数:

game_index INDEX chess_data2 (namew ASC, tournament ASC, date ASC)

不幸的是,我的查询速度相当慢(我写了14并在较小的数据集上测试了它们,甚至在8天内完成了1次)。下面是一个简化版本,我在2小时前提出但仍然没有结果。

SELECT Sum(result) 
INTO   temp 
FROM   chess_data2 t1 
WHERE  id IN (SELECT t2.id 
              FROM   chess_data2 t2 
              WHERE  t1.tournament = t2.tournament 
                AND  t1.namew = t2.namew 
                AND  t1.date < t2.date) 

我的问题:

  1. 我能否在SQL中更快地完成这项工作(更快,在我的i7-4710HQ和12GB内存中,在不到10天内完成14次类似查询?)。也许通过事先明确排序?
  2. 我能以更快的速度实现目标的其他方式吗?我试图在Python中使用循环来天真地编写代码并且性能更差,但我听说C对于这些东西更好 - 但是如何好多了?
  3. 我使用Python 3.5进行估算,使用psycopg2来处理SQL。

    编辑:感谢大家提供的有用回复。我设法成功地使用索引来极快地进行一些查询,例如这一个:

    # Number of points that the white player has so far accrued throughout the tournament
    (SELECT coalesce(SUM(result),0) from chess_data2 t2
    where (t1.namew = t2.namew) and t1.tournament = t2.tournament
    and t1.date > t2.date  and t1.date < t2.date + 90)
    + SELECT coalesce(SUM(1-result),0) from chess_data2 t2
    where (t1.namew = t2.nameb) and t1.tournament = t2.tournament
    and t1.date > t2.date and t1.date < t2.date + 90 ) AS result_in_t_w
    from chessdata2 t1
    

    现在只需要约60秒,这是可以接受的。然而,出于某种原因,计数选择像这样一个超过半小时(我没有等待更长时间)来计算:

    # Number of games that the white player has so far played in the tournament
    (SELECT count(*) from chess_data t2 where (t1.namew = t2.namew) and
    t1.tournament = t2.tournament and t1.date > t2.date and t1.date < t2.date + 90)
    + (SELECT coalesce(count(*),0) from chess_data2 t2
    where (t1.namew = t2.nameb) and t1.tournament = t2.tournament
    and t1.date > t2.date and t1.date < t2.date + 90) AS games_t_w from chess_data2 t1
    

    我想我是以错误的方式使用索引但是我不知道什么是错的,它与以前的基本相同但不是求和结果列而是计算总和行......它有意义吗?

2 个答案:

答案 0 :(得分:1)

如果你想加快执行查询,你可以创建用于连接的列索引(使用where clausule的外键和列)。 但是添加索引会导致插入和更新速度变慢,并且会增加空间光盘所需的速度。

答案 1 :(得分:1)

不知道为什么要使用IN。我试图简化你的查询并失去更多的逻辑。

我相信这相当于

SELECT sum(result) INTO temp 
FROM chess_data2 t1 

你可能想要

SELECT tournament, namew, sum(result) 
FROM chess_data2 t1 
GROUP BY tournament, namew

SELECT tournament, namew, sum(result) 
FROM chess_data2 t1 
WHERE tournament = @tournament
  AND namew = @namew