- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
使用 Azure 表存储时遇到了巨大的性能瓶颈。我的愿望是使用表作为一种缓存,因此一个漫长的过程可能会导致数百到数千行数据。然后可以通过分区键和行键快速查询数据。
查询工作得非常快(仅使用分区和行键时非常快,有点慢,但在搜索特定匹配项的属性时仍然可以接受)。
但是,插入和删除行都非常缓慢。
澄清
我想澄清一下,即使插入一批 100 个项目也需要几秒钟。这不仅仅是数千行总吞吐量的问题。当我只插入 100 时,它会影响我。
这是对我的表执行批量插入的代码示例:
static async Task BatchInsert( CloudTable table, List<ITableEntity> entities )
{
int rowOffset = 0;
while ( rowOffset < entities.Count )
{
Stopwatch sw = Stopwatch.StartNew();
var batch = new TableBatchOperation();
// next batch
var rows = entities.Skip( rowOffset ).Take( 100 ).ToList();
foreach ( var row in rows )
batch.Insert( row );
// submit
await table.ExecuteBatchAsync( batch );
rowOffset += rows.Count;
Trace.TraceInformation( "Elapsed time to batch insert " + rows.Count + " rows: " + sw.Elapsed.ToString( "g" ) );
}
}
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Starting asynchronous request to http://127.0.0.1:10002/devstoreaccount1.
Microsoft.WindowsAzure.Storage Verbose: 4 : b08a07da-fceb-4bec-af34-3beaa340239b: StringToSign = POST..multipart/mixed; boundary=batch_6d86d34c-5e0e-4c0c-8135-f9788ae41748.Tue, 30 Jul 2013 18:48:38 GMT./devstoreaccount1/devstoreaccount1/$batch.
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Preparing to write request data.
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Writing request data.
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Waiting for response.
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Response received. Status code = 202, Request ID = , Content-MD5 = , ETag = .
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Response headers were processed successfully, proceeding with the rest of the operation.
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Processing response body.
Microsoft.WindowsAzure.Storage Information: 3 : b08a07da-fceb-4bec-af34-3beaa340239b: Operation completed successfully.
iisexpress.exe Information: 0 : Elapsed time to batch insert 100 rows: 0:00:00.9351871
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Starting asynchronous request to http://127.0.0.1:10002/devstoreaccount1.
Microsoft.WindowsAzure.Storage Verbose: 4 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: StringToSign = POST..multipart/mixed; boundary=batch_7e3d229f-f8ac-4aa0-8ce9-ed00cb0ba321.Tue, 30 Jul 2013 18:47:41 GMT./devstoreaccount1/devstoreaccount1/$batch.
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Preparing to write request data.
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Writing request data.
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Waiting for response.
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Response received. Status code = 202, Request ID = , Content-MD5 = , ETag = .
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Response headers were processed successfully, proceeding with the rest of the operation.
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Processing response body.
Microsoft.WindowsAzure.Storage Information: 3 : 4c271cb5-7463-44b1-b2e5-848b8fb10a93: Operation completed successfully.
iisexpress.exe Information: 0 : Elapsed time to batch delete 100 rows: 0:00:00.6524402
635109046781264034
滴答声:
caf06fca-1857-4875-9923-98979d850df3: Starting synchronous request to https://?.table.core.windows.net/.; TraceSource 'Microsoft.WindowsAzure.Storage' event
635109046810104314
看到了这个日志。滴答声:
caf06fca-1857-4875-9923-98979d850df3: Preparing to write request data.; TraceSource 'Microsoft.WindowsAzure.Storage' event
635109046811645418
结尾。包含插入的刻度:
caf06fca-1857-4875-9923-98979d850df3: Operation completed successfully.; TraceSource 'Microsoft.WindowsAzure.Storage' event
static async Task BatchInsert( CloudTable table, List<ITableEntity> entities )
{
int rowOffset = 0;
var tasks = new List<Task>();
while ( rowOffset < entities.Count )
{
// next batch
var rows = entities.Skip( rowOffset ).Take( 100 ).ToList();
rowOffset += rows.Count;
string partition = "$" + rowOffset.ToString();
var task = Task.Factory.StartNew( () =>
{
Stopwatch sw = Stopwatch.StartNew();
var batch = new TableBatchOperation();
foreach ( var row in rows )
{
row.PartitionKey = row.PartitionKey + partition;
batch.InsertOrReplace( row );
}
// submit
table.ExecuteBatch( batch );
Trace.TraceInformation( "Elapsed time to batch insert " + rows.Count + " rows: " + sw.Elapsed.ToString( "F2" ) );
} );
tasks.Add( task );
}
await Task.WhenAll( tasks );
}
public ActionResult Index( string returnUrl )
{
ViewBag.ReturnUrl = returnUrl;
Task.Factory.StartNew( () =>
{
TableTest();
} );
return View();
}
static Random random = new Random();
static double RandomDouble( double maxValue )
{
// the Random class is not thread safe!
lock ( random ) return random.NextDouble() * maxValue;
}
void TableTest()
{
// Retrieve storage account from connection-string
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting( "CloudStorageConnectionString" ) );
// create the table client
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
// retrieve the table
CloudTable table = tableClient.GetTableReference( "test" );
// create it if it doesn't already exist
if ( table.CreateIfNotExists() )
{
// the container is new and was just created
Trace.TraceInformation( "Created table named " + "test" );
}
Stopwatch sw = Stopwatch.StartNew();
// create a bunch of objects
int count = 28000;
List<DynamicTableEntity> entities = new List<DynamicTableEntity>( count );
for ( int i = 0; i < count; i++ )
{
var row = new DynamicTableEntity()
{
PartitionKey = "filename.txt",
RowKey = string.Format( "$item{0:D10}", i ),
};
row.Properties.Add( "Name", EntityProperty.GeneratePropertyForString( i.ToString() ) );
row.Properties.Add( "Data", EntityProperty.GeneratePropertyForString( string.Format( "data{0}", i ) ) );
row.Properties.Add( "Value1", EntityProperty.GeneratePropertyForDouble( RandomDouble( 10000 ) ) );
row.Properties.Add( "Value2", EntityProperty.GeneratePropertyForDouble( RandomDouble( 10000 ) ) );
row.Properties.Add( "Value3", EntityProperty.GeneratePropertyForDouble( RandomDouble( 1000 ) ) );
row.Properties.Add( "Value4", EntityProperty.GeneratePropertyForDouble( RandomDouble( 90 ) ) );
row.Properties.Add( "Value5", EntityProperty.GeneratePropertyForDouble( RandomDouble( 180 ) ) );
row.Properties.Add( "Value6", EntityProperty.GeneratePropertyForDouble( RandomDouble( 1000 ) ) );
entities.Add( row );
}
Trace.TraceInformation( "Elapsed time to create record rows: " + sw.Elapsed.ToString() );
sw = Stopwatch.StartNew();
Trace.TraceInformation( "Inserting rows" );
// batch our inserts (100 max)
BatchInsert( table, entities ).Wait();
Trace.TraceInformation( "Successfully inserted " + entities.Count + " rows into table " + table.Name );
Trace.TraceInformation( "Elapsed time: " + sw.Elapsed.ToString() );
Trace.TraceInformation( "Done" );
}
static async Task BatchInsert( CloudTable table, List<DynamicTableEntity> entities )
{
int rowOffset = 0;
var tasks = new List<Task>();
while ( rowOffset < entities.Count )
{
// next batch
var rows = entities.Skip( rowOffset ).Take( 100 ).ToList();
rowOffset += rows.Count;
string partition = "$" + rowOffset.ToString();
var task = Task.Factory.StartNew( () =>
{
var batch = new TableBatchOperation();
foreach ( var row in rows )
{
row.PartitionKey = row.PartitionKey + partition;
batch.InsertOrReplace( row );
}
// submit
table.ExecuteBatch( batch );
Trace.TraceInformation( "Inserted batch for partition " + partition );
} );
tasks.Add( task );
}
await Task.WhenAll( tasks );
}
iisexpress.exe Information: 0 : Elapsed time to create record rows: 00:00:00.0719448
iisexpress.exe Information: 0 : Inserting rows
iisexpress.exe Information: 0 : Inserted batch for partition $100
...
iisexpress.exe Information: 0 : Successfully inserted 28000 rows into table test
iisexpress.exe Information: 0 : Elapsed time: 00:01:07.1398928
Successfully inserted 904 rows into table org1; TraceSource 'w3wp.exe' event
Elapsed time: 00:00:01.3401031; TraceSource 'w3wp.exe' event
Successfully inserted 4130 rows into table org1; TraceSource 'w3wp.exe' event
Elapsed time: 00:00:07.3522871; TraceSource 'w3wp.exe' event
Successfully inserted 28020 rows into table org1; TraceSource 'w3wp.exe' event
Elapsed time: 00:00:51.9319217; TraceSource 'w3wp.exe' event
最佳答案
好的,第三个回答有魅力吗?
http://blogs.msdn.com/b/windowsazurestorage/archive/2010/11/06/how-to-get-most-out-of-windows-azure-tables.aspx
一些东西 - 存储模拟器 - 来自一位认真研究它的 friend 。
“一切都在单个数据库中的单个表中(更多分区不会影响任何事情)。每个表插入操作至少是 3 个 sql 操作。每个批次都在一个事务内。根据事务隔离级别,这些批次将受到限制并行执行的能力。
由于 sql server 的行为,串行批处理应该比单个插入更快。 (单个插入本质上是每次刷新到磁盘的小事务,而真正的事务作为一个组刷新到磁盘)。”
使用多个分区的 IE 不会影响模拟器的性能,但它会影响真正的 azure 存储。
还启用日志记录并稍微检查您的日志 - c:\users\username\appdata\local\developmentstorage
批量大小为 100 似乎提供了最佳的实际性能,关闭 naggle,关闭期待 100,加强连接限制。
还要确保您不会意外插入重复项,这会导致错误并减慢一切。
并针对真实存储进行测试。有一个相当不错的库可以为您处理大部分内容 - http://www.nuget.org/packages/WindowsAzure.StorageExtensions/ ,只需确保您实际在添加上调用 ToList ,例如在枚举之前它不会真正执行。此外,该库使用 dynamictableentity,因此序列化的性能很小,但它确实允许您使用没有 TableEntity 内容的纯 POCO 对象。
~ JT
关于c# - 痛苦地缓慢 Azure 表插入和删除批处理操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17955557/
我知道如何通过iPhone开发创建sqlite数据库、向其中插入数据、删除行等,但我试图以编程方式删除整个数据库本身,但没有得到任何帮助。请有人指导我如何通过代码从设备中删除/删除整个 sqlite
请帮助指导如何在 Teradata 中删除数据库。 当我运行命令DROP DATABASE database_name时,我收到错误消息: *** Failure 3552 Cannot DROP d
Azure 警报规则的删除命令似乎不起作用,尝试了下面的方法,它返回状态为无内容,并且警报未被删除 使用的命令Remove-AzAlertRule -ResourceGroup "RGName"-Na
我在 flex 搜索中为大约50000个视频建立了索引,但是当它达到52000左右时,所有数据都被删除。嗯,这对我来说真的很奇怪,我没有为ES设置任何Heap大小或最小或最大大小的内存大小,因此它们没
我正在处理的问题是表单错误“输入由字母、数字、下划线或连字符组成的有效‘slug’。” 以下是我的表单字段验证: def clean_slug(self): slug = self.c
阅读文档,我希望 $("#wrap2").remove(".error") 从 中删除所有 .error 元素#wrap2。然而看看这个 JSFiddle: http://jsfiddle.net/h
嗨,我第一次尝试发现 laravel 我从 laravel 4.2 开始,我刚刚创建了一个新项目,但我误以为我写了这样的命令行 composer create-project laravel/lara
我已经在网上搜索了很长一段时间,但我找不到如何完全删除 apache 2.4 。 使用: Windows 7 c:\apache24\ 我已经尝试了所有命令,但没有任何效果。 httpd -k shu
可能是一个简单的答案,所以提前道歉(最少的编码经验)。 我正在尝试从任何列中删除具有特定字符串(经济 7)的任何行,并且一直在尝试离开此线程: How to drop rows from pandas
有几种方法可以删除/移除 vector 中的项目。 我有一个指针 vector ,我需要在类的析构函数中删除所有指针。 什么是最有效/最快甚至最安全的方式? // 1º std::for_each(v
我安装了一个 VNC 服务器并在某处阅读了我必须安装 xinetd 的信息。稍后我决定删除 VNC 服务器,所以我也删除了 xinetd。似乎 xinetd 删除了一些与 plesk 相关的文件,如果
我制作了一个从我们的服务器下载视频的应用。问题是: 当我取消下载时,我打电话: myAsyncTask.cancel(true) 我注意到,myAsyncTask 并没有在调用取消时停止...我的 P
是否可以在使用DELETE_MODEL删除模型之前检查模型是否存在我试图避免在尝试删除尚未创建的模型时收到错误消息。基本上我正在寻找对应的: DROP TABLE IF EXISTS 但对于模型。 最
我已经有了这个代码: 但它仍然会生成一个表行条目。 我想做的是,当输入的数量为0时,表行将被删除。请耐心等待,因为我是 php 和 mySQL 编码新手。 最佳答案 您忘记执行查询。应该是 $que
在 SharePoint 中,如果您删除/修改重复日历条目的单次出现,则不会真正删除/修改任何内容 - 相反,会创建一个新条目,告诉 SP 对于特定日期,该事件不存在或具有新参数. 因此,这可以通过删
在 routes.php 中我有以下路由: Route::post('dropzone', ['as' => 'dropzone.upload', 'uses' => 'AdminPhotoContr
在我的应用程序中,我正在尝试删除产品。当我第一次删除产品时,它会成功并且 URL 更改为/remove_category/15。我正在渲染到同一页面。现在,当我尝试删除另一个产品时,网址更改为/rem
这个问题被问了很多次,但给出的答案都是 GNU sed 特定的。 sed -i '' "/${FIND}/,+2d""$FILE" 给出“预期的上下文地址”错误。 有人可以给我一个例子,说明如何使用
在使用 V3 API 时,我找不到任何方法来删除和清理 Google map 。 我已经在 AJAX 站点中运行它,所以我想完全关闭它而无需重新加载页面。 我希望有一个 .unload() 或 .de
是否可以创建一个 Azure SQL 数据库用户来执行以下操作: 针对所有表和 View 进行 SELECT 创建/更改/删除 View 但用户不应该不拥有以下权限: 针对任何表或 View 插入/更
我是一名优秀的程序员,十分优秀!