问题:在提供的代码中,我试图索引~26000个地理围栏(多边形)。我已经尝试了许多组合:1)插入数据和2)索引数据,为简洁起见,有些数据未在代码中显示。我用预建索引导入了所有数据;导入数据然后制作索引并制作索引并部分导入数据并等待非陈旧索引。在所有情况下,它会占用所有内存并失败(失败,我的意思是我等待30分钟才能完成索引过程)。一个有趣的观察发生在具有预建索引的部分插入中:它总是开始占用大约1790个条目的所有内存。
环境:我已在2台机器上测试过:1)4 GB Ram,双核2.56 CUP 2)12 GB Ram,i7 CPU。我使用Visual Studio 2012(这应该不重要)使用RavenDB build 2230定向.NET 4.0。这里使用的唯一外部库(除了RavenDB客户端库)是NetTopologySuite(NuGet)。
附注和背景:我正在使用2个内存数据结构进行空间计算:KD树和带静态数据的R树(无插入/删除/更新)。现在,我的项目中添加了一个新步骤,需要每天更新/插入一些数据;因为我搜索了一个替换,以消除这部分内务的负担,我想出了SQLite R-Tree模块。它足够快(使用一些并行编程+它是一个大多数只读数据库)。到目前为止,RavenDB并不是一个选择(战略决策等)但我喜欢玩它而且令人失望。确切地说,我喜欢RavenDB 960,我真的对RavenDB 2230感到生气。
我使用了内存中的树并使用~3,000,000个多边形测试了SQLite(再次确切地称为“边界框”)并且未能将RavenDB用于~26,000个多边形。我真的希望我做错了。
代码:
namespace MyApp
{
static partial class Program
{
static void Main(string[] args)
{
Initialization();
InitializeIndexes();
// MODE 1:
// OneTimeImport(-1, 1024, true);
// MODE 2:
// OneTimeImport(-1, 1024, false);
// MODE 3:
// PartialImport(64); and PartialImport(32); and PartialImport(16);
}
static void PartialImport(int len)
{
bool finished = false;
int index = 0;
// read finished from file
if (finished)
{
return;
}
// read index from file, if not exists then set it to 0
index = OneTimeImport(index, len, true);
if (index == 0)
{
finished = true;
}
// write index and finished to file
return;
}
static int OneTimeImport(int start, int len, bool waitForIndexing)
{
var counter = start < 0 ? 0 : start;
using (var reader = new StreamReader(@"D:\PATH\DATA.TXT", Encoding.UTF8))
using (var session = Store.OpenSession())
{
session.Advanced.MaxNumberOfRequestsPerSession = int.MaxValue - 1;
if (len < 0) len = 16;
IEnumerable<string> lines = null;
if (start < 0) { lines = reader.Lines(); }
else { lines = reader.Lines().Skip(start).Take(len); }
foreach (var line in lines)
{
var parts = line.Split(new string[] { "|" }, StringSplitOptions.None);
var lm = new Area();
lm.Description = parts[5];
var poly = string.Empty;
if (!string.IsNullOrWhiteSpace(parts[8]))
{
try
{
var list = new List<Coordinate>();
var pairs = parts[8].Split(';');
foreach (var p in pairs)
{
var coor = p.Split(',');
var lon = coor[0].ToDouble();
var lat = coor[1].ToDouble();
list.Add(new Coordinate(lon, lat));
}
if (list.Count > 0)
{
list.Add(list[0]);
var ring = new LinearRing(list.ToArray());
poly = new Polygon(ring).ToString();
}
}
catch { } // some logging
}
lm.Polygon = poly;
session.Store(lm);
counter++;
if (counter % len == 0)
{
session.SaveChanges();
if (waitForIndexing) while (Store.DatabaseCommands.GetStatistics().StaleIndexes.Length > 0) Thread.Sleep(10);
}
Trace.WriteLine(counter);
}
session.SaveChanges();
if (waitForIndexing) while (Store.DatabaseCommands.GetStatistics().StaleIndexes.Length > 0) Thread.Sleep(500);
}
return counter;
}
static void Initialization()
{
Store = new DocumentStore { ConnectionStringName = "LoxConnectionString" };
Store.Initialize();
}
static void InitializeIndexes()
{
IndexCreation.CreateIndexes(typeof(Program).Assembly, Store);
}
public static IEnumerable<string> Lines(this StreamReader reader)
{
string line = null;
while ((line = reader.ReadLine()) != null) yield return line;
}
public static double ToDouble(this string s)
{
double d = 0;
double.TryParse(s, out d);
return d;
}
public static DocumentStore Store { get; private set; }
}
public class Area
{
public string Id { get; set; }
public string Description { get; set; }
public string Polygon { get; set; }
}
public class AreaIndex : AbstractIndexCreationTask<Area>
{
public AreaIndex()
{
Map = docs => from doc in docs
select new
{
doc.Description,
_ = SpatialGenerate("AreaPolygon", doc.Polygon)
};
}
}
}