Привязка данных к представлению данных - PullRequest
1 голос
/ 04 августа 2009

Есть ли у вас какие-либо предложения относительно моего кода ниже, которые могут вам понадобиться для повышения производительности? Это платформа .NET 2.0, и DataTable привязывается к DataGridview. Данные загружаются в Datatable через .ReadXML (), а не из базы данных. Там может быть где угодно от 80 до 100к записей. Массив Terms () - это то, что пользователь передал для поиска. Таким образом, «боб тако» будет термины (0) = «боб», термины (1) = «тако». У меня есть регулярное выражение, которое поддерживает любые цитируемые условия. Так что «боб тако» будет на одном элементе массива. Есть ли способ лучше? Я попытался использовать Dataview, так как он имеет лучшую производительность, но не похоже, что я могу использовать оператор LIKE. Любые предложения приветствуются, я бы очень хотел ускорить это.

Public Function Search(ByVal Terms() As String, ByRef ResidentTBL As DataTable) As DataTable
        'Dim t As Long = Now.Ticks

        Dim j As Integer
        Dim newdt As New DataTable("Users")
        Dim newtable As New DataTable
        newtable = ResidentTBL.Clone

        Dim termsceiling As Integer
        termsceiling = Terms.GetUpperBound(0)
        Dim filterstr As String = String.Empty
        Dim foundrows() As DataRow
        Dim sortOrder As String = "displayname ASC"
        Dim tempstr As String

        For j = 0 To termsceiling
            'remedy any invalid sql characters
            tempstr = Terms(j).Trim.ToUpper
            tempstr = tempstr.Replace("'", "''")
            tempstr = tempstr.Replace("*", "")
            tempstr = tempstr.Replace("%", "")

            'assemble the sql query

            filterstr = filterstr & _
        "((column1 LIKE '" & tempstr & "%') OR " & _
        "(column2 LIKE '" & tempstr & "%') OR " & _
        "(column3 LIKE '" & tempstr & "%') OR " & _
        "(column4 LIKE '" & tempstr & "%') OR " & _
        "(column5 LIKE '" & tempstr & "%') OR " & _
        "(column6 LIKE '" & tempstr & "%') OR " & _
        "(column7 LIKE '" & tempstr & "%') OR " & _
        "(column8 LIKE '" & tempstr & "%') OR " & _
        "(column9 LIKE '" & tempstr & "%') OR " & _
        "(column10 LIKE '" & tempstr & "%'))"


            'if there are further iterations append an AND  (user typed more than one term)
            If termsceiling > 0 And j <> termsceiling Then
                filterstr = filterstr & " AND "
            End If
        Next j

        filterstr = "(" & filterstr & ")"  'wrap the entire query

        foundrows = ResidentTBL.Select(filterstr, sortOrder)

        For i = 0 To foundrows.Length - 1
            newtable.ImportRow(foundrows(i))
        Next i

        newdt = newtable

        'Begin Debugging Code:
        't = Now.Ticks - t
        'MessageBox.Show("Took " & (t / 10000000) & " seconds.")
        'End Debugging Code:

        Return newdt
    End Function

Ответы [ 4 ]

3 голосов
/ 04 августа 2009

Я проверил несколько вопросов и решил переписать свой ответ, чтобы быть более точным. Посмотрите на обработку строк. Каждый раз, когда вы присваиваете строке новое значение, создается новая строка. Примечание: вы делаете много больших строковых операций в цикле. Во-первых, вы берете значение и делаете некоторые замены. Затем вы делаете большую конкатенацию (раздел «как»). Попробуйте использовать String.Format или - намного, намного лучше - использовать класс StringBuilder. Строковые операции могут значительно снизить производительность.

1 голос
/ 04 августа 2009

Я бы предложил не создавать фильтр, а делать что-то вроде

foreach (DataRow row in ResidentTBL.Rows)
    if (IsMatch(row))
          newtable.ImportRow(row);

где метод IsMatch реализует логику в вашем фильтре. Это должно дать вам немного более точно настроенный контроль. Подборщики DataTable спроектированы так, чтобы быть универсальными, поэтому они используют алгоритм стиля сочетания ключей. Это не всегда самый оптимальный способ найти запись.

Обратите внимание, мой пример - C #, вам нужно будет настроить VB, но я не такой, как стих.

0 голосов
/ 04 августа 2009

Рассматривали ли вы преобразование ваших алгоритмов поиска для использования LINQ в XML? Это избавит вас от тяжести DataTable.

Вы можете просто загрузить свой XML-файл в XmlDocument и выполнить LINQ-запросы к элементам в объекте XML в памяти. Больше вопросов и ответов вы можете найти на странице Linq-To-Xml tag . Возможно, начните с LINQ To XML: как это работает?

Существует метод расширения, который действительно поможет вам: Contains()

Если вы хотите продолжить реализацию DataTable, вот дополнительная информация об использовании LINQ с DataTables .

0 голосов
/ 04 августа 2009

Я бы сделал это по-разному для двух учетных записей: во-первых, я бы запустил запрос к базе данных и заполнил бы данные только правильными (отфильтрованными) данными.

Во-вторых, этот способ использования LIKE будет проходить каждый раз через все записи, делая его медленным, если у вас много пользователей. В этой ситуации я в итоге реализую «поисковую систему для бедняков», которая в основном разбирает каждый текст из этих полей на слова и вставляет в другую таблицу каждое слово с соответствующим идентификатором пользователя. Эта таблица может быть проиндексирована, и поиск будет осуществляться непосредственно с помощью «=», а не «LIKE», что значительно ускоряет поиск.

Редактировать : Отсутствие базы данных усложняет ситуацию. Тем более, что у вас много данных, и я не знаю, есть ли индексация или оптимизация при таком поиске. Если у вас есть метод кэширования данных между запросами, вы можете создать еще один источник данных с проанализированными данными. Пока пользователь ищет токены того же типа, он должен работать, но для того, чтобы найти «bob taco» как два слова одно рядом с другим, вам нужно сохранить положение слов при разборе данных и поиске. соответственно (это немного усложняет).

Например:

ID, Text
1, Hangs out at Bob Taco joint
2, Hates Bob and his taco

дал бы что-то вроде этого:

ID, Key, Pos
1, Hangs, 1
1, out, 2
1, at, 3
1, Bob, 4
1, Taco, 5
1, joint, 6
2, Hates, 1
2, Bob, 2
2, and, 3
2, his, 4
2, taco, 5

Так что теперь вам нужно искать идентификаторы, которые содержат как bob, так и taco, и разница между их значениями Pos должна быть 1. Например, ID 2 не должен быть найден, так как Pos - это 2 и 5.

Я сделал это, используя временные таблицы в SQL. Если вам нужно работать только с памятью, это может стать сложнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...