代码之家  ›  专栏  ›  技术社区  ›  Jon

提高填充列表的SQL性能<t>

  •  0
  • Jon  · 技术社区  · 15 年前

    我在数据库中有200000条记录,其中pk是varchar(50条)

    每5分钟我做一次 SELECT COUNT(*) FROM TABLE

    如果结果大于list.count,则执行

    "SELECT * FROM TABLE WHERE PRIMARYKEY NOT IN ( " + myList.ToCSVString() + ")"
    

    我之所以这样做是因为记录是通过另一个进程添加到表中的。

    这个查询需要很长时间才能运行,我还认为它抛出了一个OutofMemoryException

    有没有更好的方法来实现这一点?

    谢谢

    5 回复  |  直到 15 年前
        1
  •  4
  •   Sam Saffron James Allen    15 年前

    SQL Server对此有解决方案,请添加 timestamp 列,每次触摸表中的任何行时,时间戳都将增大。

    为timestamp列添加索引。

    不只是在内存中存储ID,而是存储ID和最后一个时间戳。

    更新:

    • 选择最大时间戳
    • 选择旧最大时间戳和当前最大时间戳之间的所有行
    • 把它合并到列表中

    处理删除有点复杂,但是如果您使用墓碑而不是删除,则可以实现删除。

        2
  •  1
  •   Itay Karo    15 年前

    你能换一下桌子吗?
    如果是这样,您可能希望添加一个新的自动递增列,该列将用作pk。 TableId .

    在每一个 SELECT 保存最大ID,然后在下一步选择添加位置 TableId > maxId .

        3
  •  0
  •   goenning    15 年前

    创建一个int-pk,并使用如下内容:

    "SELECT * FROM TABLE WHERE MY_ID > " + myList.Last().Id;
    

    如果无法更改pk,请创建另一列,其类型为date,默认值为now(),并使用该列查询新项。

        4
  •  0
  •   Jamie Ide    15 年前

    在数据库中为主键创建另一个具有单列的表。当应用程序启动时,将pks插入此表。然后,您可以通过选择直接检测添加的键,而不是检查计数:

    select PrimaryKey from Table where PrimaryKey not in (select PrimaryKey from OtherTable) 
    
        5
  •  0
  •   Bengie    15 年前

    如果这个csv列表很大,我建议将您的文件加载到一个temp表中,在其上放置一个索引,并在其中执行一个左联接,其中为空

    select tbl.*
    from table tbl
    left join #tmpTable tmp on tbl.primarykey = tmp.primarykey
    where tmp.primary key is null
    

    编辑:主键不应是varchar。它应该几乎总是递增的int/bigint。这会容易得多。从primarykey>@lastknownkey的表中选择*

    打那个设计这个的数据库程序员。P

    这种设计也会导致索引碎片化,因为行不会以线性方式插入。

    推荐文章