在 SQL Server 2014 中写入基础表后立即查询视图

Querying a view immediately after writing to underlying tables in SQL Server 2014

我遇到一个问题,如果我写入 table(using Linq-to-SQL),它是视图的依赖项,然后立即转身并查询该视图以检查写入的影响(使用与数据库的新连接,因此使用新的数据上下文),写入的影响不会立即显示出来,但会占用几秒钟出现。这只是偶尔发生(可能每 10,000 次左右写入 10-20 次)。

这是视图的定义:

CREATE VIEW [Position].[Transactions]
WITH SCHEMABINDING
AS
(
  SELECT
    Account,
    Book,
    TimeAPIClient AS DateTimeUtc,
    BaseCcy AS Currency,
    ISNULL(QuantityBase, 0) AS Quantity,
    ValueDate AS SettleDate,
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType
  FROM Trades.FxSpotMF
  WHERE IsCancelled = 0

  UNION ALL

  SELECT
    Account,
    Book,
    TimeAPIClient AS DateTimeUtc,
    QuoteCcy AS Currency,
    ISNULL(-QuantityBase * Rate, 0) AS Quantity,
    ValueDate AS SettleDate,
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType
  FROM Trades.FxSpotMF
  WHERE IsCancelled = 0

  UNION ALL

  SELECT
    Account,
    Book,
    ExecutionTimeUtc AS DateTimeUtc,
    BaseCcy AS Currency,
    ISNULL(QuantityBase, 0) AS Quantity,
    ValueDate AS SettleDate,
    ISNULL(CAST(1 AS tinyint), 1) AS TransactionType
  FROM Trades.FxSpotManual
  WHERE IsCancelled = 0

  UNION ALL

  SELECT
    Account,
    Book,
    ExecutionTimeUtc AS DateTimeUtc,
    QuoteCcy AS Currency,
    ISNULL(-QuantityBase * Rate, 0) AS Quantity,
    ValueDate AS SettleDate,
    ISNULL(CAST(1 AS tinyint), 1) AS TransactionType
  FROM Trades.FxSpotManual
  WHERE IsCancelled = 0

  UNION ALL

  SELECT
    Account,
    Book,
    ExecutionTimeUtc AS DateTimeUtc,
    BaseCcy AS Currency,
    ISNULL(SpotQuantityBase, 0) AS Quantity,
    SpotValueDate AS SettleDate,
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType
  FROM Trades.FxSwap

  UNION ALL

  SELECT
    Account,
    Book,
    ExecutionTimeUtc AS DateTimeUtc,
    QuoteCcy AS Currency,
    ISNULL(-SpotQuantityBase * SpotRate, 0) AS Quantity,
    SpotValueDate AS SettleDate,
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType
  FROM Trades.FxSwap

  UNION ALL

  SELECT
    Account,
    Book,
    ExecutionTimeUtc AS DateTimeUtc,
    BaseCcy AS Currency,
    ISNULL(ForwardQuantityBase, 0) AS Quantity,
    ForwardValueDate AS SettleDate,
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType
  FROM Trades.FxSwap

  UNION ALL

  SELECT
    Account,
    Book,
    ExecutionTimeUtc AS DateTimeUtc,
    QuoteCcy AS Currency,
    ISNULL(-ForwardQuantityBase * ForwardRate, 0) AS Quantity,
    ForwardValueDate AS SettleDate,
    ISNULL(CAST(2 AS tinyint), 2) AS TransactionType
  FROM Trades.FxSwap

  UNION ALL

  SELECT
    Account,
    c.Book,
    TimeUtc AS DateTimeUtc,
    Currency,
    ISNULL(Amount, 0) AS Quantity,
    SettleDate,
    ISNULL(CAST(3 AS tinyint), 3) AS TransactionType
  FROM Trades.Commission c
  JOIN Trades.Payment p
    ON c.UniquePaymentId = p.UniquePaymentId
    AND c.Book = p.Book
)

虽然这是 Linq-to-SQL 生成的查询,用于写入底层 tables 之一:

INSERT INTO [Trades].[FxSpotMF] ([UniqueTradeId], [BaseCcy], [QuoteCcy], [ValueDate], [Rate], [QuantityBase], [Account], [Book], [CounterpartyId], [Counterparty], [ExTradeId], [TimeAPIClient], [TimeAPIServer], [TimeExchange], [TimeHandler], [UniqueOrderId], [IsCancelled], [ClientId], [SequenceId], [ExOrdId], [TradeDate], [OrderCycleId], [CycleIndex])
  VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21, @p22)

这是 Linq-to-SQL 生成的用于检查写入效果的查询:

SELECT
  SUM([t0].[Quantity]) AS [Item2],
  [t0].[Currency] AS [Item1]
FROM [Position].[Transactions] AS [t0]
WHERE ([t0].[Book] = @p0)
AND ([t0].[DateTimeUtc] < @p1)
GROUP BY [t0].[Currency]

此外,这是生成写入的 Linq-to-SQL 代码(使用 F# 类型提供程序):

type Schema = Microsoft.FSharp.Data.TypeProviders.DbmlFile<"TradeDb.dbml", ContextTypeName="TradeDb"> 

use db = new Schema.TradeDb(connectionString)
let trade = new Schema.Trades_FxSpotMF()
(* omitted: set object properties corresponding to column values here... *)
db.Trades_FxSpotMF.InsertOnSubmit(trade)
db.SubmitChanges()

虽然这是生成读取的相应 Linq-to-SQL:

use db = new Schema.TradeDb(connectionString)
query { for t in db.Position_Transactions do
        where ( t.Book = book &&
                t.DateTimeUtc < df.MaxExecutionTimeExcl
              )
        groupBy t.Currency into group
        let total = query { for x in group do sumBy x.Quantity }
        select (group.Key, total)
      }
|> Map.ofSeq

我原以为 System.Data.Linq.DataContext.SubmitChanges() 只会 return 一旦写入事务完成,并且视图的任何后续查询都必须包含写入的效果...我是什么 missing/doing错了?

您已经创建了具有模式绑定的视图

CREATE VIEW [Position].[Transactions]
WITH SCHEMABINDING

并且有 8 个联合操作和来自 4 tables

的 9 个查询
FROM Trades.FxSpotMF  --2times
  WHERE IsCancelled = 0

FROM Trades.FxSpotManual --2 times
  WHERE IsCancelled = 0

FROM Trades.FxSwap -- 4 times

FROM Trades.Commission c
  JOIN Trades.Payment p
    ON c.UniquePaymentId = p.UniquePaymentId
    AND c.Book = p.Book

在每次插入这些 table 之一后刷新视图,系统可能需要几秒钟,并且您的 select 查询 运行 在插入后立即。 可能发生插入在 0~1 毫秒内执行到 table 但刷新视图需要超过 100 毫秒并且 select 由于视图是从服务器缓存提供的查询未命中

您的 Link 到 SQL 是否有可能检查写入效果是在查看旧的缓存数据?尝试使用上下文对象的 refresh method 预先刷新缓存。在对象上使用 RefreshMode.OverwriteCurrentValues

你可以试试 table hints

CREATE VIEW [Position].[Transactions]
WITH SCHEMABINDING
AS
(
  SELECT
    Account,
    Book,
    TimeAPIClient AS DateTimeUtc,
    BaseCcy AS Currency,
    ISNULL(QuantityBase, 0) AS Quantity,
    ValueDate AS SettleDate,
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType
  FROM Trades.FxSpotMF WITH(NOLOCK)
  WHERE IsCancelled = 0

  UNION ALL

  SELECT
    Account,
    Book,
    TimeAPIClient AS DateTimeUtc,
    QuoteCcy AS Currency,
    ISNULL(-QuantityBase * Rate, 0) AS Quantity,
    ValueDate AS SettleDate,
    ISNULL(CAST(0 AS tinyint), 0) AS TransactionType
  FROM Trades.FxSpotMF WITH(NOLOCK)
  WHERE IsCancelled = 0
  ...
)

Alos 检查 this 博客条目,在我的情况下使用 nolock 提示解决问题。

我终于弄明白了:数据库写入是在它们自己的线程中完成的,主线程在检查结果之前等待所有写入线程完成。但是在检查所有线程是否完成的代码中有一个错误,导致主线程过早地进行检查。