public override void LoadXFlow(IEnumerable <XElement> xflow, Dictionary <string, string> orig_ids) { IEnumerable <object> flow = xflow.Select(record => { string id = record.Attribute(ONames.rdfabout).Value; // Корректируем идентификатор if (orig_ids.TryGetValue(id, out string idd)) { id = idd; } int rec_type = store.CodeEntity(ONames.fog + record.Name.LocalName); int id_ent = store.CodeEntity(id); object[] orecord = new object[] { id_ent, (new object[] { new object[] { store.cod_rdftype, rec_type } }).Concat( record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null) .Select(subel => { int prop = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName); string resource = subel.Attribute(ONames.rdfresource).Value; if (orig_ids.TryGetValue(resource, out string res)) { if (res != null) { resource = res; } } return(new object[] { prop, store.CodeEntity(resource) }); })).ToArray() , record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null) .Select(subel => { int prop = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName); var xlang = subel.Attribute("{http://www.w3.org/XML/1998/namespace}lang"); string lang = xlang == null ? "" : xlang.Value; return(new object[] { prop, subel.Value, lang }); }) .ToArray() }; return(orecord); }); store.Load(flow); }
// Новая реализация загрузки базы данных private void FillDb(IEnumerable <FogInfo> fogFlow) { // Пока каждый раз чистим базу данных Store.Clear(); // Вычисление "важных" кодов var codRdftype = Store.CodeEntity("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); // Зафиксирован? 0; // Готовим битовый массив для отметки того, что хеш id уже "попадал" в этот бит int rang = 24; // пока предполагается, что число записей (много) меньше 16 млн. int mask = ~((-1) << rang); int baVolume = mask + 1; System.Collections.BitArray bitArr = new System.Collections.BitArray(baVolume); // Хеш-функция будет ограничена rang разрядами, массив и функция нужны только временно int Hash(string s) => s.GetHashCode() & mask; // Словарь, фиксирующий максимальную дату для заданного идентификатора, первая запись не учитывается Dictionary <string, DateTime> lastDefs = new Dictionary <string, DateTime>(); // Первый проход сканирования фог-файлов. В этом проходе определяется набор повторно определенных записей и // формируется словарь lastDefs foreach (FogInfo fi in fogFlow) { switch (fi.Vid) { // Чтение фога case ".fog": { fi.Fogx = XElement.Load(fi.Pth); foreach (XElement xElement in fi.Fogx.Elements()) { XElement record = ConvertXElement(xElement); // Обработаем "странные" delete и replace if (record.Name == ONames.fogi + "delete") { string idd = record.Attribute(ONames.rdfabout)?.Value ?? record.Attribute("id")?.Value; // Если нет атрибута mT, временная отметка устанавливается максимальной, чтобы "забить" другие отметки string mTvalue = record.Attribute("mT") == null ? DateTime.MaxValue.ToString(CultureInfo.InvariantCulture) : record.Attribute("mT")?.Value; CheckAndSet(bitArr, Hash, lastDefs, idd, mTvalue); continue; } if (record.Name == ONames.fogi + "substitute") { continue; // пока не обрабатываем } string id = record.Attribute(ONames.rdfabout)?.Value; CheckAndSet(bitArr, Hash, lastDefs, id, record.Attribute("mT")?.Value); } fi.Fogx = null; break; } case ".fogp": break; } } // Второй проход сканирования фог-файлов. В этом проходе, для каждого фога формируется поток записей в // объектном представлении, потом этот поток добавляется в store foreach (FogInfo fi in fogFlow) { switch (fi.Vid) { // Чтение фога case ".fog": case ".fogx": { fi.Fogx = XElement.Load(fi.Pth); IEnumerable <object> flow = fi.Fogx.Elements() .Select(xrec => ConvertXElement(xrec)) // Обработаем delete и replace. delete доминирует (по времени), но в выходной поток ничего не попадает // substitute - не обрабатываем .Where(record => record.Name != ONames.fogi + "delete" && record.Name != ONames.fogi + "substitute") // Отфильтруем записи с малыми временами. т.е. если идентификатор есть в словаре, но он меньше. // Если он больше, то не фильтруем, а словарный вход корректируем .Where(record => { var xAbout = record.Attribute(ONames.rdfabout); if (xAbout == null) { return(true); } string id = xAbout.Value; if (!lastDefs.ContainsKey(id)) { return(true); } DateTime mT = DateTime.MinValue; string mTvalue = record.Attribute("mT")?.Value; if (mTvalue != null) { mT = DateTime.Parse(mTvalue); } DateTime last = lastDefs[id]; if (mT < last) { return(false); // пропускаем } if (mT == last) { return(true); // берем } // if(mT > last) // берем и корректируем last { lastDefs.Remove(id); lastDefs.Add(id, mT); return(true); } }) .Select(record => { string id = record.Attribute(ONames.rdfabout).Value; int rec_type = Store.CodeEntity(ONames.fog + record.Name.LocalName); int id_ent = Store.CodeEntity(id); object[] orecord = new object[] { id_ent, (new object[] { new object[] { codRdftype, rec_type } }).Concat( record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null) .Select(subel => { int prop = Store.CodeEntity( subel.Name.NamespaceName + subel.Name.LocalName); return(new object[] { prop, Store.CodeEntity(subel.Attribute(ONames.rdfresource).Value) }); })).ToArray(), record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null) .Select(subel => { int prop = Store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName); return(new object[] { prop, subel.Value }); }) .ToArray() }; return(orecord); }); Store.Load(flow); fi.Fogx = null; break; } case ".fogp": break; } } Store.Build(); Store.Flush(); GC.Collect(); }
public static void Main20() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); System.Random rnd = new Random(); //string path = "../../../../data/Databases/"; string path = "C:/Home/data/Databases/"; int fnom = 0; Func <Stream> GenStream = () => File.Open(path + (fnom++), FileMode.OpenOrCreate); Console.WriteLine("Start TestConsoleApp (Main32)"); TripleRecordStore store = new TripleRecordStore(GenStream, path, new string[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" , "http://fogid.net/o/name" , "http://fogid.net/o/age" , "http://fogid.net/o/person" , "http://fogid.net/o/photo-doc" , "http://fogid.net/o/reflection" , "http://fogid.net/o/reflected" , "http://fogid.net/o/in-doc" }); int npersons = 40_000; int nphotos = npersons * 2; int nreflections = npersons * 6; bool toload = true; bool tocode = true; if (toload) { sw.Restart(); store.Clear(); var persons = Enumerable.Range(0, npersons).Select(i => npersons - i - 1) .Select(c => new object[] { -c - 1, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 3 } }, new object[] { new object[] { 1, "p" + c }, new object[] { 2, "" + 33 } } }); var persons2 = Enumerable.Range(0, npersons).Select(i => npersons - i - 1) .Select(c => store.CodeRecord(new object[] { "" + c, new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/person" } }, new object[] { new object[] { "http://fogid.net/o/name", "p" + c }, new object[] { "http://fogid.net/o/age", "" + 33 } } })); var persons3 = Enumerable.Range(0, npersons).Select(i => npersons - i - 1) .Select(c => store.CodeRecord(new object[] { "" + c, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 3 } }, new object[] { new object[] { 1, "p" + c }, new object[] { 2, "" + 33 } } })); var photos = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1) .Select(c => new object[] { -(c + npersons) - 1, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 4 } }, new object[] { new object[] { 1, "f" + c } } }); var photos2 = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + npersons), new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/photo-doc" } }, new object[] { new object[] { "http://fogid.net/o/name", "f" + c } } })); var photos3 = Enumerable.Range(0, nphotos).Select(i => nphotos - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + npersons), // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 4 } }, new object[] { new object[] { 1, "f" + c } } })); var reflections = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1) .Select(c => new object[] { -(c + 3 * npersons) - 1, // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 5 }, new object[] { 6, -1 - (rnd.Next(npersons)) }, new object[] { 7, -1 - (rnd.Next(nphotos) + npersons) } }, new object[] { } }); var reflections2 = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + 3 * npersons), new object[] { new object[] { "http://www.w3.org/1999/02/22-rdf-syntax-ns#type", "http://fogid.net/o/reflection" }, new object[] { "http://fogid.net/o/reflected", "" + rnd.Next(npersons) }, new object[] { "http://fogid.net/o/in-doc", "" + (rnd.Next(nphotos) + npersons) } }, new object[] { } })); var reflections3 = Enumerable.Range(0, nreflections).Select(i => nreflections - i - 1) .Select(c => store.CodeRecord(new object[] { "" + (c + 3 * npersons), // Это "прямой" код не требующий кодирования через таблицу new object[] { new object[] { 0, 5 }, new object[] { 6, "" + rnd.Next(npersons) }, new object[] { 7, "" + (rnd.Next(nphotos) + npersons) } }, new object[] { } })); if (tocode) { store.Load(persons2.Concat(photos2).Concat(reflections2)); //store.Load(persons3.Concat(photos3).Concat(reflections3)); } else { store.Load(persons.Concat(photos).Concat(reflections)); } store.Build(); sw.Stop(); Console.WriteLine($"Load ok. duration={sw.ElapsedMilliseconds}"); } //else { sw.Restart(); store.Refresh(); sw.Stop(); Console.WriteLine($"Refresh for Phototeka {npersons} persons. Duration={sw.ElapsedMilliseconds}"); } // ПОлукодирование иногда кодирование, иногда нет Func <int, int> HCode = nom => tocode?store.Code("" + nom) : -1 - nom; // Проверка int code = HCode(npersons * 2 / 3); var query1 = store.GetRecord(code); Console.WriteLine(store.ToTT(query1)); // Скорость выполнения запросов int nprobe = 10000; sw.Restart(); for (int i = 0; i < nprobe; i++) { int c = HCode(rnd.Next(npersons)); var ob = store.GetRecord(c); } sw.Stop(); Console.WriteLine($"{nprobe} GetRecord() ok. duration={sw.ElapsedMilliseconds}"); // Надо найти все фотографии, в которых отражается персона с выбранным (случайно) кодом. sw.Restart(); int total = 0; nprobe = 1000; for (int i = 0; i < nprobe; i++) { int c = HCode(rnd.Next(npersons)); var query2 = store.GetRefers(c).Cast <object[]>().ToArray(); var q3 = query2 .Select(ob => ((object[])ob[1]).Cast <object[]>() .First(dupl => (int)dupl[0] == 7)); var q4 = q3 .Select(bb => store.GetRecord((int)bb[1])).ToArray(); total += query2.Count(); } sw.Stop(); Console.WriteLine($"{nprobe} persons for photos ok. duration={sw.ElapsedMilliseconds} total={total}"); //var likes = store.Like("p" + 666); //foreach (var like in likes) //{ // Console.WriteLine($"like {store.ToTT(like)}"); //} sw.Restart(); total = 0; for (int i = 0; i < 1000; i++) { string id = "p" + rnd.Next(npersons / 10 + 1, npersons); total += store.Like(id).Count(); } sw.Stop(); Console.WriteLine($"{nprobe} likes for persons ok. duration={sw.ElapsedMilliseconds} total={total}"); }