Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

LINQом из DataTable по индексу?

404  
Murr патриот13.11.22 11:43
Murr
NEW 13.11.22 11:43 

Я так надеюсь,что все знают что такое индекс на таблице SQL-сервера, для чего нужен и как используется.

Считаем что с сервером все понятно.


Теперь переползаем на клиента - имеем те же данные что на сервере и эти данные достаточно "тяжелые".

Т.е. записи длинные, записей много и записи не сортированы.

Работа с данными (пока) традиционная - через DataTable - загрузили и ищем.

Чтобы не сильно мучатся - ищем LINQом.

Известно, что поиск будет многократный - т.е. любое ускорение - на пользу.


Отсюда два вопроса:

1. Как на DataTable повесить произвольный индекс?

Т.е. есть 150-200 полей и 3 из них мне нужны как индекс.

Про вариант проэмулировать индекс вторичным ключем - слепить вторую таблицу, дистинктнуть в нее эти поля, сделать их первичным ключем и определить реляцию - знаю, но не нравится - хочется именно индекс по таблице без головной боли с поддержанием синхронизации.


2. Как принудить LINQ использовать индекс (пусть и сурогатный) при выполнении поиска?

#1 
  simplename постоялец13.11.22 21:47
13.11.22 21:47 
в ответ Murr 13.11.22 11:43
1. Как на DataTable повесить произвольный индекс?Т.е. есть 150-200 полей и 3 из них мне нужны как индекс.Про вариант проэмулировать индекс вторичным ключем - слепить вторую таблицу, дистинктнуть в нее эти поля, сделать их первичным ключем и определить реляцию - знаю, но не нравится - хочется именно индекс по таблице без головной боли с поддержанием синхронизации.

зачем? новые таблицы вы создавать не желаете, значит остается выбирать записи из ВСЕХ (не пропустить бы чего).

2. Как принудить LINQ использовать индекс (пусть и сурогатный) при выполнении поиска?

элементарно, уоттсон! постройте правильно ваш запрос, и linq его исполнит с высокой точностью.
шукаємо записи, где пропертиз id0: ID0, id1: ID1, id2: ID2
var q = from rec in records where rec.id0 == ID0 && rec.id1 == ID1 && rec.id2 == ID2 select rec; (или что вам оттуда нужно выбрать).
или я чего-то недопонл.


нужно, мне кажется, прежде всего между двумя вариантами выбрать: мы согласны что-нибудь заморочить один раз, чтобы потом раз! и достал что надо!

, или не согласны, но тогда мы не можем исключить просмотра при каждом запросе всей таблицы. LINQ'ом, или кем-либо еще. при чем здесь "суррогантый иднеск"?

#2 
Murr патриот13.11.22 22:27
Murr
NEW 13.11.22 22:27 
в ответ simplename 13.11.22 21:47

зачем?

-----

Смотрим чутка выше - в первый пост.

Хочется определять и использовать индекс для ускорения процесса.


остается выбирать записи из ВСЕХ

-----

Когда-то давно удавалось ускорять выполнение с 20-30 минут до десятков секунд просто построив и используя индекс.

Но там он строился по массиву (array) ручками с кучей кода обвязки...


и linq его исполнит с высокой точностью.

-----

Ну а мне помимо точности еще и скорости хочется.

Пусть в твоем records 100K записей.

При этом ID2 принимает 3 значения 1,2,3 при этом 1 - 50К-1, 2 - 50К-1, 3 - две записи.

Сколько надо сканить records чтобы выбрать записи с ID2==3?



при чем здесь "суррогантый иднеск"?

-----

Видимо стоит ознакомится с тем что такое индексы и как они используются.

#3 
alex445 коренной житель13.11.22 23:15
NEW 13.11.22 23:15 
в ответ Murr 13.11.22 11:43, Последний раз изменено 13.11.22 23:17 (alex445)

Здесь можно пошерстить, включая разные ответы и комменты

https://stackoverflow.com/questions/23802401/how-to-get-in...


Но там, как я понял, не строят полноценный индекс, а именно что "эмулируют" его через линк-запрос. Оптимизирует ли при этом сам линк что-то - надо разбираться. Скорее всего нет.


Или там вообще уже готовый индекс в таблице есть, и вопрошающему надо лишь поискать по нему через линк.

#4 
Murr патриот14.11.22 00:53
Murr
NEW 14.11.22 00:53 
в ответ alex445 13.11.22 23:15

"эмулируют" его

-----
Ничего не эмулируют - выморочно получают номер строки в таблице.

#5 
alex445 коренной житель14.11.22 01:33
NEW 14.11.22 01:33 
в ответ Murr 14.11.22 00:53

"Эмулируют" - в смысле, что пытаются делать запрос с учётом всех столбцов индексса. Но опросить по индексу, как я понимаю, это не сравнить все столбцы. Индекс должен включать в себя какую-то оптимизацию - например, хешнуть все столбцы индекса. Тогда опрос должен идти по этуму жешу (типа как в словаре), а после нахождения строки с нужным хешем нужен подзапрос для вытаскивания конкретных столбцов этой строки.


Впрочем, возможно, что ЛИНК сам распознаёт подобный запрос (со сравнением по куче столбцов) - мол, если это сравнение по столбцам индекса, то он внутри себя переводит этот запрос на поиск по индексу.


Это я всё написал, не очень понимая, что такое индекс и как он работает - так, почитал немного.

#6 
alex445 коренной житель14.11.22 01:39
NEW 14.11.22 01:39 
в ответ alex445 14.11.22 01:33

А почему вы до сих пор работаете с DataTable и DataSet? Это ж пипец какой-то - по сравнению с EF как в доисторическую эпоху окунулся. Кстати, как раз голостроковые запросы. У меня на древнючем проекте это дерьмо не просто само по себе, а ещё и обёрнутое в самописный фреймворк (с построением запросов вида queryObject.AddWhere(string criteria)... AddOrderBy(string criteria)) и шлифануто сверху корявой первой версией NHibernate. И на EF переходить категорически не хотят.

#7 
MrSanders коренной житель14.11.22 09:54
NEW 14.11.22 09:54 
в ответ Murr 13.11.22 11:43

Что-то я не понял, так тебе нормальный индекс в таблице нужен или что-то нахреноверченное линком на клиенте?

#8 
alex445 коренной житель14.11.22 10:52
NEW 14.11.22 10:52 
в ответ MrSanders 14.11.22 09:54

Как я понял - нормальный индекс не нужен, а нужно работать линком на клиенте так, как будто нормальный индекс есть. Т.е. всё же нахреноверченное на клиенте. Вот я пример показал - "эмулируем" индекс. Но по сути это обычный запрос со сравнением по нескольким полям.

#9 
Murr патриот14.11.22 15:08
Murr
NEW 14.11.22 15:08 
в ответ alex445 14.11.22 01:33

возможно

-----

Чтобы что-то было возможно нужно чтобы оно было.

Пока же вопрос стоит об наличии/создании индекса.


как я понимаю

-----

Гоогла - ISAM - там подробно и понятно.

Да и для общего развития полезно.

#10 
Murr патриот14.11.22 15:13
Murr
NEW 14.11.22 15:13 
в ответ MrSanders 14.11.22 09:54

Первая хотелка - повесить индекс на DataTable. Это на клиенте, естественно.

Вторая хотелка - заставить LINQ использовать повешенный в первой хотелке индекс для акселерации.

#11 
  simplename постоялец14.11.22 20:21
NEW 14.11.22 20:21 
в ответ Murr 13.11.22 22:27, Последний раз изменено 14.11.22 20:24 (simplename)
Смотрим чутка выше - в первый пост.Хочется определять и использовать индекс для ускорения процесса.

То есть не просто и рыбку съесть, и далее по присказке?

Тогда что-то такое (например).

хочется еще быстрее: распараллелить по количеству кернов в процессоре.

еще быстрее? использовать python. не знаю, может сишарп тоже может использовать для вычислений gpu?


#12 
Murr патриот15.11.22 02:24
Murr
NEW 15.11.22 02:24 
в ответ simplename 14.11.22 20:21

и далее по присказке?

----

Ну а как иначе?


Существенное из ссылки

Problem:

The DataTable.Select method creates a "System.Data.Select" class instance internally, and this "Select" class creates indexes based on the fields (columns) specified in the query. The Select class makes re-use of the indexes it had created but the DataTable implementation does not re-use the Select class instance hence the indexes are re-created every time DataTable.Select is invoked.


Вот что-то похожее мне и интересно, но в варианте когда индекс создается мною, поддерживается самой таблицей,и ре-юзается.


еще быстрее?

-----

Быстрее бывает разное.

Одно быстрее - число систем в кластере.

Другое быстрее - уменьшение количества операций.

Сейчас меня интересует второе.

#13