如何提高写入数据库的性能?

时间:2020-03-06 14:33:38  来源:igfitidea点击:

我们记录值,并且只在表中记录一次。当我们向表中添加值时,我们必须每次都进行查找以查看它是否需要插入值或者仅获取ID。我们在表上有一个索引(不在主键上),但是大约有350,000行(所以花10秒来做10个这些值)。

所以或者

  • 我们想出一种优化它的方法
  • 将此功能剥去,或者
  • 记录这些值时,请执行完全不同的操作。

解决方案

为了清楚起见,索引位于表中的(可能是varchar或者nvarchar)字段上,对吗?不是PK?

好的,在我们编辑之后:我们正在对一个大的(n)varchar文本字段进行索引查找。即使索引可能很慢-我们仍在进行2个大字符串比较。我真的不是实现此目的的好方法,但是有一些初始的SWAGS:

  • 计算要记录的文本的哈希,并将其存储在数据库中以供后续查找
  • 如另一位海报建议的那样,存储所有行,并在查询中过滤出重复项(或者每晚进行批处理,无论
  • 不要检查重复项。捕获异常可能仍然比查找便宜*
  • 雇用一个记忆力非常好的人,用鼠标快速禁食。当要记录一条消息时,使用接受/拒绝提示将其闪烁到其屏幕上。如果输入内容是伪造的,请点击"拒绝"

*是的,我知道我对此会被低估,但有时实用主义才行得通。

我们写入表的频率与从表中读取的频率。如果我们频繁写入和偶尔读取,请考虑始终进行插入,然后在执行选择时处理折叠值。

如果要将所有内容放在一个表中,请考虑将它们分成单独的表以减小大小,或者禁止在表中使用分区。

在35万行的表上进行索引查找需要1秒钟?对我来说,这听起来确实太慢了。.我们确定没有其他问题吗?

没有看到实际查询,我只能一概而论。但是,我将提供以下想法/建议:

1)我们是否已验证索引确实用于查找查询?如果它是具有高基数的索引,则它应该快得多。

2)我们可以将这两个操作组合成一个存储过程,该存储过程首先查找该行,然后在必要时进行插入....类似:

IF EXISTS (SELECT ID FROM YourTable WHERE ID = @ID_to_look_for)
      @ID_exists = 1
ELSE
      @ID_exists = 0

如果我们发布确切的查询内容,也许我可以提供更详细的答案。

我不确定我是否有足够的信息来回答这个问题,但是这里仍然有一些想法:

  • 如果我们尚未这样做,则可以在一个SQL中完成插入和验证操作(插入表(值)(选择表的左外部联接,id为null的表))
  • 我们是否正在使用DAL层或者存储过程来执行此操作?我们是否控制用于选择/插入的SQL?如果不这样做,则可能希望用户使用SQL Profiler来检查正在发送到数据库的内容,以防其格式使索引无效。

除了尝试查找外,我们还可以尝试插入值。如果该表被设计为拒绝重复记录,即它具有主键或者唯一索引,则插入将出错。只需捕获插入错误即可,如果收到错误,则照常获取ID。

我同意查找不会花那么长时间,但是为什么要让引擎解析查询,映射路径,进行查找,然后在将结果同时插入之前将结果发送给我们,然后才能插入。

我们还可以研究:

  • 假设有改进的空间,索引编制会更好
  • 更改数据库的物理布局以提高IO
  • 增加SQL Server可用的内存

"当我们向表中添加值时,我们每次都必须进行查找,以查看它是否需要插入值或者仅获取ID。"

我们过去称其为" upsert"操作。

try:
    UPDATE log SET blah blah blah WHERE key = key;
except Missing Key:
    INSERT INTO log(...) VALUES(...);

我们从来没有做过自己的查询来查看键是否存在,因为那是UPDATE语句的工作。

首先,查看查询计划以查看其作用。这将告诉我们是否正在使用索引。单行测试/插入的一秒钟太慢。对于35万行,它足够长,可以对缓存的表进行表扫描。

第二。查看服务器的物理布局。我们是否有类似日志和数据共享同一磁盘的内容?

第三,检查唯一键上的索引列是否与select查询的谓词顺序相同。顺序上的差异可能会使查询优化器混乱。

第四,考虑唯一键上的聚簇索引。如果这是我们查找行的主要方式,则由于表数据与聚簇索引物理存储在一起,因此将减少磁盘访问。有关聚集索引的说明,请参见此。用足够的填充系数设置表格。

除非我们有Blob列,否则350k行远低于分区应该起作用的阈值。该大小表应完全适合高速缓存。

我们是否偶然使用光标?在这么小的桌子上做自己说的事情应该不需要十秒钟。

我们需要基于集合的更新和插入语句。

  • 排除连接性和驱动程序问题-确保以相同方式在同一数据库上执行的其他操作足够快
  • 确保我们独立于可能在同一事务中运行的其他操作来衡量此操作
  • 确保我们没有锁定方案-停止其他所有操作,只执行管理工具中的查找和更新序列即可。
  • 检查查找是否更昂贵(99%)或者磁盘写入是否昂贵-尽管即使对于慢速磁盘,10秒也太高了。为了完整起见,请执行此操作。
  • 检查查询是否正在使用索引-可能正在进行表扫描。
  • 如果用于索引的列是文本字段,请通过在具有索引的非文本列上进行查找来检查文本索引是否是问题的根源。如果是这样,请尝试更改逻辑以使用PK或者使用哈希代替文本。