// ==================== Динамика =================== private int SetStr(string s) { int code = (int)table.Count(); long off = table.AppendElement(new object[] { code, s }); str_offsets.AppendElement(off); dyna_index.Add(s, code); // нужен итоговый Flush по двум последовательностям return(code); }
public long AppendPair(object[] pair, bool dynindex) { long offset = keyvalue_seq.AppendElement(pair); if (dic1 != null && dynindex) { dic1.Add((int)pair[0], offset); } return(offset); }
// Запись кода по строке public int GetSetCode(string s) { int nom; if (dic.TryGetValue(s, out nom)) { } else { nom = (int)ids.Count(); long off = ids.AppendElement(s); offs.AppendElement(off); dic.Add(s, nom); } return(nom); }
//static string path = "Databases/"; public static void Main12() { string path = ""; Random rnd = new Random(); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); Console.WriteLine("Start experiment with UniversalSequense"); // Тип основной таблицы PType tp_person = new PTypeRecord( new NamedType("id", new PType(PTypeEnumeration.integer)), new NamedType("name", new PType(PTypeEnumeration.sstring)), new NamedType("age", new PType(PTypeEnumeration.real))); Stream f1 = File.Open(path + "Databases/f1.bin", FileMode.OpenOrCreate); UniversalSequence <int> keyvalue_seq = new UniversalSequence <int>(tp_person, f1); // Теперь надо добавить индекс и использовать его Func <object[], int> keyFunc = (object[] re) => (int)re[0]; // вводим индекс Stream f2 = File.Open(path + "Databases/f2.bin", FileMode.OpenOrCreate); Stream f3 = File.Open(path + "Databases/f3.bin", FileMode.OpenOrCreate); UniversalSequence <int> keys = new UniversalSequence <int>(new PType(PTypeEnumeration.integer), f2); UniversalSequence <long> offsets = new UniversalSequence <long>(new PType(PTypeEnumeration.longinteger), f3); int nelements = 10_000_000; Console.WriteLine($"Sequence of {nelements} elements"); bool toload = true; int[] k_arr = new int[nelements]; long[] o_arr = null; if (toload) { sw.Restart(); keyvalue_seq.Clear(); var query = Enumerable.Range(0, nelements).Select(i => new object[] { nelements - i - 1, "" + (nelements - i - 1), 33.3 }); o_arr = new long[nelements]; int pos = 0; foreach (var el in query) { long off = keyvalue_seq.AppendElement(el); k_arr[pos] = keyFunc(el); o_arr[pos] = off; pos++; } keyvalue_seq.Flush(); // Сортировка Array.Sort(k_arr, o_arr); // Надо записать массивы keys.Clear(); offsets.Clear(); for (int i = 0; i < nelements; i++) { keys.AppendElement(k_arr[i]); offsets.AppendElement(o_arr[i]); } keys.Flush(); offsets.Flush(); o_arr = null; sw.Stop(); Console.WriteLine($"Load ok. duration={sw.ElapsedMilliseconds}"); } else { // Надо прочитать массивы for (int i = 0; i < nelements; i++) { object ob = i == 0 ? keys.GetElement(keys.ElementOffset(0L)) : keys.GetElement(); k_arr[i] = (int)ob; //object ob2 = i == 0 ? offsets.GetElement(offsets.ElementOffset(0L)) : offsets.GetElement(); //o_arr[i] = (long)ob2; } } int k1 = nelements * 2 / 3; int nprobe = 10_000; sw.Restart(); // Прямая выборка for (int i = 0; i < nprobe; i++) { int k2 = rnd.Next(nelements); int ind = Array.BinarySearch(k_arr, k2); //long offset = o_arr[ind]; long offset = (long)offsets.GetElement(offsets.ElementOffset(ind)); var r = (object[])keyvalue_seq.GetElement(offset); } sw.Stop(); Console.WriteLine($"BinarySearch and GetElement ({nprobe} times). duration={sw.ElapsedMilliseconds}"); /* * // Собственно таблица * TableView tab_person = new TableView(path + "person", tp_person); * Func<object, int> person_code_keyproducer = v => (int)((object[])((object[])v)[1])[0]; * IndexKeyImmutable<int> ind_arr_person = new IndexKeyImmutable<int>(path + "person_ind") * { * Table = tab_person, * KeyProducer = person_code_keyproducer, * Scale = null * }; * //ind_arr_person.Scale = new ScaleCell(path + "person_ind") { IndexCell = ind_arr_person.IndexCell }; * IndexDynamic<int, IndexKeyImmutable<int>> index_person = new IndexDynamic<int, IndexKeyImmutable<int>>(true) * { * Table = tab_person, * IndexArray = ind_arr_person, * KeyProducer = person_code_keyproducer * }; * tab_person.RegisterIndex(index_person); * * int nelements = 1000000; * bool toload = true; // Загружать или нет новую базу данных * if (toload) * { * sw.Restart(); * // Очистим ячейки последовательности и индекса * tab_person.Clear(); * * IEnumerable<object> flow = Enumerable.Range(0, nelements) * .Select(i => * { * int id = nelements - i; * string name = "=" + id.ToString() + "="; * double age = rnd.NextDouble() * 100.0; * return new object[] { id, name, age }; * }); * tab_person.Fill(flow); * * // Теперь надо отсортировать индексный массив по ключу * tab_person.BuildIndexes(); * sw.Stop(); * Console.WriteLine("Load ok. duration for {0} elements: {1} ms", nelements, sw.ElapsedMilliseconds); * } * * // Проверим работу * int search_key = nelements * 2 / 3; * var ob = index_person.GetAllByKey(search_key) * .Select(ent => ((object[])ent.Get())[1]) * .FirstOrDefault(); * if (ob == null) throw new Exception("Didn't find person " + search_key); * Console.WriteLine("Person {0} has name {1}", search_key, ((object[])ob)[1]); * * // Засечем скорость выборок * sw.Restart(); * for (int i = 0; i < 1000; i++) * { * search_key = rnd.Next(nelements) + 1; * ob = index_person.GetAllByKey(search_key) * .Select(ent => ((object[])ent.Get())[1]) * .FirstOrDefault(); * if (ob == null) throw new Exception("Didn't find person " + search_key); * string nam = (string)((object[])ob)[1]; * } * sw.Stop(); * Console.WriteLine("Duration for 1000 search in {0} elements: {1} ms", nelements, sw.ElapsedMilliseconds); */ }
public void CalculateStaticIndex() { if (dic1 != null) { dic1 = new Dictionary <int, long>(); // Не используем накопленное содержание } if (dic2 != null) { dic2 = new Dictionary <int, long>(); } int ind = 0; int nelements = (int)keyvalue_seq.Count(); keys_arr = new int[nelements]; long[] offs_arr = new long[nelements]; keyvalue_seq.Scan((off, obj) => { int key = (int)((object[])obj)[0]; keys_arr[ind] = key; offs_arr[ind] = off; ind++; return(true); }); Array.Sort(keys_arr, offs_arr); keys.Clear(); //keys.Fill(new object[0]); List <int> keys_list = new List <int>(); offsets.Clear(); //offsets.Fill(new object[0]); // Будем убирать повторы int prev_key = Int32.MaxValue; long prev_offset = Int64.MinValue; for (int i = 0; i < nelements; i++) { int key = keys_arr[i]; long offset = offs_arr[i]; if (key != prev_key) { // Надо сохранить пару, но только если предыдущий ключ не фиктивный if (prev_key != Int32.MaxValue) { keys.AppendElement(prev_key); keys_list.Add(prev_key); offsets.AppendElement(prev_offset); } prev_key = key; prev_offset = offset; } else { if (offset > prev_offset) { prev_offset = offset; } } } if (nelements > 0) { keys.AppendElement(prev_key); keys_list.Add(prev_key); offsets.AppendElement(prev_offset); } // Доделаем массив ключей keys_arr = keys_list.ToArray(); keys.Flush(); offsets.Flush(); // Внешние индексы, если есть if (exindexes != null) { foreach (var exindx in exindexes) { //var q = exindx.exkeys; //// long[] offs_arr = new long[nelements]; //int[] ext_arr = exindx.exkeys.ElementValues().Cast<int>().ToArray(); //int[] pri_arr = exindx.prikeys.ElementValues().Cast<int>().ToArray(); //Array.Sort(ext_arr, pri_arr); //exindx.exkeys.Clear(); //exindx.exkeys.Fill(new object[0]); //foreach (int k in ext_arr) exindx.exkeys.AppendElement(k); //exindx.prikeys.Clear(); //exindx.prikeys.Fill(new object[0]); //foreach (int k in pri_arr) exindx.prikeys.AppendElement(k); //exindx.exkeys.Flush(); //exindx.prikeys.Flush(); long ne = exindx.exprikeys.Count(); int[] ext_arr = new int[ne]; int[] pri_arr = new int[ne]; for (int i = 0; i < ne; i++) { object[] ep = (object[])exindx.exprikeys.GetElement(exindx.exprikeys.ElementOffset(i)); ext_arr[i] = (int)ep[0]; pri_arr[i] = (int)ep[1]; } Array.Sort(ext_arr, pri_arr); exindx.exprikeys.Clear(); for (int i = 0; i < ne; i++) { exindx.exprikeys.AppendElement(new object[] { ext_arr[i], pri_arr[i] }); } exindx.exprikeys.Flush(); pri_arr = null; exindx.key_arr = ext_arr; } } }