C# 如何处理只需要;最后一句话;数据库C中符号的值#

C# 如何处理只需要;最后一句话;数据库C中符号的值#,c#,sql-server,azure,stockquotes,C#,Sql Server,Azure,Stockquotes,我有一个高速流的股票价格来自一个供应商。。。也许每秒5000。(约8000个不同的符号) 我的数据库中有一个表(SymbolPrice),需要用最新的最新价格进行更新 我似乎无法保持数据库更新的足够快,以处理最近的价格队列 我使用的是Azure Sql Server数据库,因此我能够将该数据库升级到支持内存表的高级版本,并使我的SymbolPrice表成为内存表。。。但仍然不够好 如果它最终跳过了一个价格,这不是问题,只要最新的价格尽快到达那里。。。所以如果我连续10次被打。。。只有最后一个需要

我有一个高速流的股票价格来自一个供应商。。。也许每秒5000。(约8000个不同的符号)

我的数据库中有一个表(SymbolPrice),需要用最新的最新价格进行更新

我似乎无法保持数据库更新的足够快,以处理最近的价格队列

我使用的是Azure Sql Server数据库,因此我能够将该数据库升级到支持内存表的高级版本,并使我的SymbolPrice表成为内存表。。。但仍然不够好

如果它最终跳过了一个价格,这不是问题,只要最新的价格尽快到达那里。。。所以如果我连续10次被打。。。只有最后一个需要写。。。这听起来很简单,除了一行中的10可能与其他符号混合

因此,我目前的解决方案是使用ConcurrentDictionary只保存最近的价格。并使用符号队列将更新推送到数据库(请参见下面的代码)。。。但这仍然不够快

解决这个问题的一个方法是简单地重复浏览整本字典。。。并用最新价格更新数据库。。。但这有点浪费,因为我也会更新值,这些值可能只会每隔几分钟更新一次,速度与每秒更新多次的值相同

有没有关于如何做得更好的想法

谢谢

  • 布莱恩

      public ConcurrentDictionary<string, QuoddLastPriceCache.PriceData> _lastPrices = new ConcurrentDictionary<string, QuoddLastPriceCache.PriceData>();
      public ConcurrentQueue<string> _lastPriceSymbolsToUpdate = new ConcurrentQueue<string>();
    
    
      public void Start()
      {
          Task.Run(() => { UpdateLastPricesTask(services); });
    
          lastPriceCache.PriceReceived += (symbol, priceData) =>
          {
              _lastPrices.AddOrUpdate(symbol, priceData, (key, value) => { return priceData; });
              _lastPriceSymbolsToUpdate.Enqueue(symbol);
          };
      }
    
      private void UpdateLastPricesTask(IServiceProvider services)
      {
          _lastPriceUpdatesRunning = true;
    
          while (_lastPriceUpdatesRunning)
          {
              if (_lastPriceSymbolsToUpdate.TryDequeue(out string symbol))
              {
                  if (_lastPrices.TryRemove(symbol, out QuoddLastPriceCache.PriceData priceData))
                  {
                      // write to database
                      if (_lastPriceScope == null || _lastScopeCreate + TimeSpan.FromSeconds(60 * 5) < DateTime.UtcNow)
                      {
                          if (_lastPriceScope != null)
                              _lastPriceScope.Dispose();
                          _lastPriceScope = services.CreateScope();
                      }
    
                      var unitOfWork = _lastPriceScope.ServiceProvider.GetRequiredService<IUnitOfWork>();
                      unitOfWork.SymbolPrice.UpdateLastPrice(symbol, priceData.Price, priceData.Timestamp);
                  }
              }
              else
                  Thread.Sleep(1);
          }
      }
    
    公共ConcurrentDictionary\u lastPrices=new ConcurrentDictionary();
    public ConcurrentQueue_lastPriceSymbolsToUpdate=new ConcurrentQueue();
    公开作废开始()
    {
    Task.Run(()=>{UpdateLastPricesTask(服务);});
    lastPriceCache.PriceReceived+=(符号,价格数据)=>
    {
    _AddOrUpdate(符号,priceData,(键,值)=>{returnpricedata;});
    _lastPriceSymbolsToUpdate.Enqueue(符号);
    };
    }
    私有void UpdateLastPricesTask(IServiceProvider服务)
    {
    _LastPriceUpdateRunning=true;
    while(_lastPriceUpdatesRunning)
    {
    if(_lastpricesymboltUpdate.TryDequeue(输出字符串符号))
    {
    if(_lastPrices.TryRemove(符号,out-QuoddLastPriceCache.PriceData-PriceData))
    {
    //写入数据库
    如果(_lastPriceScope==null | | | u lastScopeCreate+TimeSpan.FromSeconds(60*5)

您需要使用能够查询流的东西,SQL不是最好的工具。搜索复杂事件处理和Kafka/Event hub+流分析。

我能做的最好的方法是以下方法。。。我将最后的值保存在字典中,并添加一个是否已写入数据库的标志。。。然后遍历数据并将更新后的值写入数据库。。。这样,我只更新最近更新的值。效果很好。。。看来应该有更好的办法

    public void Start()
    {
        Task.Run(() => { UpdateLastPricesTask(services); });
        
        LastPriceCache.PriceReceived += (symbol, priceData) =>
        {
            _lastPrices.AddOrUpdate(symbol, priceData, (key, value) => { return priceData; });
        };
    }

    public ConcurrentDictionary<string, PriceData> _lastPrices = new ConcurrentDictionary<string, PriceData>();
    public bool _lastPriceUpdatesRunning;
    public DateTime _lastScopeCreate = DateTime.MinValue;
    public IServiceScope _lastPriceScope = null;

    private void UpdateLastPricesTask(IServiceProvider services)
    {
        _lastPriceUpdatesRunning = true;

        while (_lastPriceUpdatesRunning)
        {
            var processed = 0;

            foreach (var symbol in _lastPrices.Keys)
            {
                if (_lastPrices.TryGetValue(symbol, out QuoddLastPriceCache.PriceData priceData))
                {
                    if (priceData.WrittenToDatabase == false)
                    {
                        // create a new scope every 5 minutes
                        if (_lastPriceScope == null || _lastScopeCreate + TimeSpan.FromSeconds(60 * 5) < DateTime.UtcNow)
                        {
                            if (_lastPriceScope != null)
                                _lastPriceScope.Dispose();
                            _lastPriceScope = services.CreateScope();
                        }

                        // write to database
                        var unitOfWork = _lastPriceScope.ServiceProvider.GetRequiredService<IUnitOfWork>();
                        unitOfWork.SymbolPrice.UpdateLastPrice(symbol, priceData.Price, priceData.Timestamp);
                        priceData.WrittenToDatabase = true;

                        processed++;
                    }
                }
            }

            if (processed > 0)
                Thread.Sleep(1);
            else
                Thread.Sleep(1000 * 1);
        }
    }
public void Start()
{
Task.Run(()=>{UpdateLastPricesTask(服务);});
LastPriceCache.PriceReceived+=(符号,价格数据)=>
{
_AddOrUpdate(符号,priceData,(键,值)=>{returnpricedata;});
};
}
公共ConcurrentDictionary_lastPrices=新ConcurrentDictionary();
公共图书馆最近的价格更新运行;
public DateTime\u lastScopeCreate=DateTime.MinValue;
公共IServiceScope_lastPriceScope=null;
私有void UpdateLastPricesTask(IServiceProvider服务)
{
_LastPriceUpdateRunning=true;
while(_lastPriceUpdatesRunning)
{
var=0;
foreach(在_lastPrices.key中的var符号)
{
if(_lastPrices.TryGetValue(符号,out-quodLastPriceCache.PriceData-PriceData))
{
if(priceData.writentodatabase==false)
{
//每5分钟创建一个新范围
如果(_lastPriceScope==null | | | u lastScopeCreate+TimeSpan.FromSeconds(60*5)0)
睡眠(1);
其他的
睡眠(1000*1);
}
}

它有多快,需要多快?在这里,您与数据库的交互方式可能非常关键,您不会显示任何代码。例如,您可以使用表值参数或JSON对更改进行批处理,并每秒左右发送一批更改。这是一个每天每秒5000项的连续流吗?数据是如何到达的、一组HTTP POST、UDP blast或betw中的某些东西