【问题标题】:FoxPro 6.0 error message - temp file is too largeFoxPro 6.0 错误信息 - 临时文件太大
【发布时间】:2017-05-22 10:18:34
【问题描述】:

这是我的 FoxPro 程序。 Select 子句导致错误。

PROCEDURE IFRS_Split_Cashflows_2_v7_4_CSV
PARAMETERS model_dir, cube2_output_path, output_path, scenario, version
temp_dir = GETENV("TEMP")

**** Load up utility function and Create an output folder ****
SET PROCEDURE TO model_dir + "\CUBE2_" + version + "\PRGS\Utilities_" + version + ".prg"
lcTextFile = cube2_output_path + "\IFRS_Split_Cashflows_2\run_" + scenario + ".csv"
Do delete_file WITH lcTextFile
Do create_folder WITH cube2_output_path + "\IFRS_Split_Cashflows_2"

**** Assign variables to the input files ****
moses_output_file = output_path + "\annuities~main10.dbf"
SELECT 0
Use (moses_output_file) ALIAS cube_output1
moses_output_file = output_path + "\annuities~main10~reinsured.dbf"
SELECT 0
Use (moses_output_file) ALIAS cube_output2
moses_output_file = output_path + "\annuities~main10~reinsurance_premium.dbf"
SELECT 0
Use (moses_output_file) ALIAS cube_output3

**** Split the group string and select relevant data ****
SELECT ;
      c1.t_from AS t_from, ;
      c1.cal_mth as calendar_month, ;
      c1.cal_yr as calendar_year, ;
      substr(c1.group,1,3) AS BUS_LINE, ;
      padr( IIF( isnumeric( strextract(c1.group, "|", "|", 1, 1), ""), ;
                 substr(c1.group,1,4) + strextract(c1.group, "|", "|", 1, 1), ;
                 strextract( c1.group,"|", "|",1, 1)), 10) AS reinsurance_book,;
      padr( strextract(c1.group, "|","|", 3,1),10) AS Esc_Index,;
      padr( IIF( left(c1.group,3) = "LRT", ;
                 strextract(c1.group, "|", "|",5,1), ;
                 strextract(c1.group,"|","|",4,1)) ,10) AS MAP_ELIG,;
      padr( IIF( left(c1.group,3) = "LRT", ;
                 strextract( trim(c1.group - "|"),"|","|", 6, 1), ;
                 strextract( trim(c1.group - "|"),"|","|", 5,1)), 10) AS MAP_STAT,;
      SUM(c1.ann_ben_if) AS ann_ben_if, ;
      SUM(c2.dth_out) AS c2death_outgo, ;
      SUM(c3.dth_out) AS c3death_outgo;
   FROM ;
      cube_output1 c1, ;
      cube_output2 c2, ;
      cube_output3 c3; 
   INTO ;
      CURSOR temp READWRITE;
   WHERE ;
          c1.t_from = 0 ;
      AND (   ( c1.t_from = c2.t_from AND c1.group = c2.group) ;
           OR ( c1.t_from = c3.t_from AND c1.group = c3.group)) ;
   group by ;
      c1.t_from, ;
      c1.cal_mth, ;
      c1.cal_yr, ;
      BUS_LINE, ;
      reinsurance_book, ;
      Esc_Index, ;
      MAP_ELIG, ;
      MAP_STAT 


**** Copy to a CSV file ****
COPY TO cube2_output_path + "\IFRS_Split_Cashflows_2\run_" + scenario + ".csv" TYPE CSV

它会生成错误,“文件 c:\users\jc\appdata\local\temp\00002jo9000h.tmp 太大。其他任务失败。”

我实际上从 select 语句中删除了几个与 c2 和 c3 相关的字段。我还将 where 子句的第一部分从 c1.t_from > 0 更改为 c1.t_from = 0,以减少观察。

错误仍然出现。我了解临时文件的文件大小上限为 2GB。大小方面,输入文件如下:c1 为 275MB,C2 为 275MB,c3 为 191MB。鉴于此,我对临时文件太大感到惊讶。为什么它太大了?有什么方法可以改进上面的 Select 语句,以正确返回请求的字段?

【问题讨论】:

  • 您需要提供一些示例数据。您正在隐式创建内部连接,但它们的大小表并不重要。 c1 中的单行可能与 c2 和 c3 中的许多行匹配,产生太多行,最终超过 2 Gb。此外,您没有给我们完整的 sql,您的似乎正在利用 VFP8 之前版本中存在的错误。您不应该以这种方式求和,这可能会导致错误的结果。
  • 我对输入数据不太熟悉,但您可能是对的。假设你是对的,最好的解决方法是什么?另外,你能详细说明你提到的错误吗?我正在使用 FP6。我已经更新了上面的代码以包含完整的程序。

标签: sql visual-foxpro foxpro


【解决方案1】:

我认为你在查询中得到了笛卡尔结果,这让你很生气。

您的查询没有使用 C2 和 C3 别名引用中的任何实际列值,只是确保在 C2 或 C3 表中的任何一个中都可以找到给定的 T_From 和 Group。

为了消除您的临时文件崩溃,我会确保您在每个 C2 和 C3 表上都有一个基于 T_From 和 Group 的索引,例如

moses_output_file = output_path + "\annuities~main10~reinsured.dbf"
Use (moses_output_file) ALIAS cube_output2 EXCLUSIVE
index on str( T_From ) + Group tag TFromGroup

moses_output_file = output_path + "\annuities~main10~reinsurance_premium.dbf"
SELECT 0
Use (moses_output_file) ALIAS cube_output3 EXCLUSIVE
index on str( T_From ) + Group tag TFromGroup

索引可以在此函数之外创建一次,并且始终保持可用。如果该索引不存在,则可以在此处使用它。

现在,查询修复。将您的 FROM/WHERE 子句更改为以下内容。我正在做的是从 C1 表到子查询结果的 SQL-JOIN。由于您只关心提取在其他表中的任何一个中都有记录的记录,因此我正在执行 PreCheck 查询以获取不同的 T_From / Group 记录。然后只提取那些 T_From = 0 的 C1 记录。

注意 PreCheck 查询也在 T_From = 0 上应用 where 子句,所以我不能只加入那些发现 T_From = 0 的组。您将完全消除任何可能的笛卡尔结果,因为内部查询只会产生 DISTINCT "Group" 记录。

选择(所有其他字段相同...最后一个字段添加逗号)

    C2Sum.C2Death_Outgo,;
    C3Sum.C3Death_Outgo;
FROM ;
    cube_output1 c1;
        LEFT JOIN ( select c2.Group,;
                           SUM(c2.dth_out) AS c2death_outgo ;
                       FROM cube_output2 c2;
                       WHERE c2.t_from = 0;
                       GROUP BY c2.Group ) C2Sum ;
           on c1.t_group = C2Sum.Group; ;
        LEFT JOIN ( select c3.Group, ;
                           SUM(c3.dth_out) AS c3death_outgo;
                       FROM cube_output3 c3 ;
                       WHERE c3.t_from = 0 ;
                       GROUP BY c3.Group ) C3Sum ;
        ON c1.t_group = C3Sum.group;
WHERE ;
        c1.t_from = 0 ;
    AND ( NOT ISNULL( c2Sum.Group )  OR NOT ISNULL( c3Sum.Group )) 

我在这里所做的是对每个单独的表进行分组,以防止它们之间出现笛卡尔。我对他们俩都进行了 LEFT-JOIN,因为不知道您的数据,每个 C2 / C3 表中可能都有一条记录,并且不想扭曲总和。

通过完成 where 子句,我正在寻找 EITHER LEFT JOIN to NOT BE NULL,这意味着给定组有一条记录。同样,任何一方或双方都可以有一个记录,因此它会被计为一次连接并且不会导致重复。

现在,由于 group by 的金额仅在组级别,并且您的 OUTER 查询是按公交线路、保险簿、索引等的更多部分进行分组,无论它们在哪个子分类中,GROUP金额对所有人都显示相同,这可能不是您要查找的内容。

最后,您的繁重解析、填充、字符串提取似乎不是对事物进行分类的好方法,但使用单独的列可能会更有效......只是一个想法。

【讨论】:

  • 感谢您抽出宝贵时间查看此内容,并为长时间的延迟表示歉意。我可以实现你的两个解决方案,但仍然存在一个问题 - 我实际上确实想从 c2 和 c3 返回值。我已经从原始的 select 语句中删除了这些,因为我相信它会节省空间。例如,我如何包含以下字段: SUM(c2.dth_out) AS c2death_outgo SUM(c3.dth_out) AS c3death_outgo 我试图将它们包含在 DRapp 的代码中,但它们不会返回值,因为它们不是其中的一部分外部选择语句。
  • @mediaeval,返回并编辑您当前帖子的结尾。显示总和如何聚合的基础。它是否也按 T_From / Group 列聚合?如果是这样,应该有点简单,一旦你完成,我会调整。
  • 我已经添加了必要的代码。代码实际上从未由 t_from & group 聚合,它实际上由 t_from 和 group 的组成部分聚合,因为它们在 select 语句中被拆分。我原以为通过 t_from 和 group 来做会简化描述。从理论上讲,它应该是相同的。谢谢
  • @mediaeval,我更新了你的主要帖子以提高查询的可读性,但也更新了我的解决方案。
  • 谢谢,这帮助很大。关于索引的一个问题。该索引是随后在代码中引用的,还是只是为了提高“分组依据”子句的速度而“存在”?
【解决方案2】:

正如 Drapp 所说,您得到的是笛卡尔(不是真的但接近它)结果,因此您的临时文件变得越来越大。如果你做一个小模型:

立方体1

t_from cal_mth cal_yr ann_be_if group
------ ------- ------ --------- -----
  0      1      2016   100        1
  0      2      2016   800        2
  1      3      2016   500        3

cube2

t_from fieldX group
------ ------ -----
  0      1      1
  0      2      1
  0      3      1

立方体3

t_from fieldY group
------ ------ -----
  0      1      2
  0      2      2
  0      3      2
  0      4      2

使用您的 SQL,这将导致从 cube1 中选择 2 行 3*4 次(您的条件与 cube2 中的 3 行和 cube3 中的 4 行匹配),这将是 24 行。由于您重复选择相同的行 3*4 次,因此您也重复了 ann_be_if 的值 3*4 次并将它们加起来将是 (800+100)*12 = 10800。这不太可能是您想要的。

当您有连接时,您不应该进行聚合(隐式或 显式)与其他表(除非你确定你不会有 这种重复 - 即加入样品客户、订单、订单项 表不会出现这种重复)。

再次阅读您的 SQL,那些第 2 和第 3 个表对结果没有任何作用,只是您只是对它们进行“存在”检查。因此,您可以将代码重写为:

**** Assign variables to the input files ****
*!* moses_output_file = output_path + "\annuities~main10.dbf"
*!* SELECT 0
*!* Use (moses_output_file) ALIAS cube_output1
*!* moses_output_file = output_path + "\annuities~main10~reinsured.dbf"
*!* SELECT 0
*!* Use (moses_output_file) ALIAS cube_output2
*!* moses_output_file = output_path + "\annuities~main10~reinsurance_premium.dbf"
*!* SELECT 0
*!* Use (moses_output_file) ALIAS cube_output3

cube_output1 = m.output_path + "\annuities~main10.dbf"
cube_output2 = m.output_path + "\annuities~main10~reinsured.dbf"
cube_output3 = m.output_path + "\annuities~main10~reinsurance_premium.dbf"

Select t_from, ;
    cal_mth As calendar_month, ;
    cal_yr As calendar_year, ;
    substr(c1.Group,1,3) As BUS_LINE, ;
    padr(Iif(isnumeric(Strextract(c1.Group,"|","|",1,1),""), ;
        substr(c1.Group,1,4) + Strextract(c1.Group,"|","|",1,1), ;
        strextract(c1.Group,"|","|",1,1)),10) As reinsurance_book, ;
    padr(Strextract(c1.Group,"|","|",3,1),10) As Esc_Index, ;
    padr(Iif(Left(c1.Group,3)="LRT",;
        strextract(c1.Group,"|","|",5,1),;
        strextract(c1.Group,"|","|",4,1)),10) As MAP_ELIG, ;
    padr(Iif(Left(c1.Group,3)="LRT",;
    strextract(Trim(c1.Group - "|"),"|","|",6,1), ;
    strextract(Trim(c1.Group - "|"),"|","|",5,1)),10) As MAP_STAT, ;
    SUM(ann_ben_if) As ann_ben_if ;
    FROM (m.cube_output1) c1 ;
    WHERE c1.t_from = 0 And ;
    exists ( Select * From (m.cube_output2) c2 ;
             Where c2.t_from = 0 And c1.Group = c2.Group ) ;
    OR ;
    exists ( Select * From (m.cube_output3) c3 ;
             Where c3.t_from = 0 And c1.Group = c3.Group ) ;
    group By t_from, calendar_month, calendar_year, ;
        BUS_LINE, reinsurance_book, Esc_Index, MAP_ELIG, MAP_STAT ;
    Into Cursor temp ;
    Readwrite


**** Copy to a CSV file ****
COPY TO (m.cube2_output_path + "\IFRS_Split_Cashflows_2\run_" + m.scenario + ".csv") TYPE CSV

【讨论】:

  • 请查看对 DRapp 帖子的回复。
  • 嗨 Cetin,感谢发帖,这有助于我理解。
猜你喜欢
  • 1970-01-01
  • 2022-06-20
  • 1970-01-01
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
相关资源
最近更新 更多