2014-11-30 2 views
1

В моей базе данных содержится около 2 миллионов строк. Это содержит набор предложений в каждой строке (не английский язык).Каков эффективный способ извлечения (выбора) данных из базы данных?

![Image of database][1] 

enter image description here

В качестве примера, если пользователь дает 'ABCD', который соответствовал с обеими строками 1,3. Поэтому оба должны выбрать. Из-за этого огромное время, затраченное на получение данных. Я использую следующий код для извлечения данных. Если какое-либо данное слово соответствует базе данных, эти строки должны быть выбраны.

 sb.append("SELECT Sentence FROM corpus Where "); 
     for(int k=0;k<wordList.size();k++){ 
      sb.append(" Sentence like '%" + wordList.get(k) + "%' OR "); 
     } 
     sb.append(" 1=0"); 
     rs2 = dbc.sqlExecute(sb.toString()); 

Это слово выбора может быть в любом месте в строке. Это может быть спереди или в середине или в конце. Моя проблема заключается в том, когда пользователь дает некоторую словосочетание, огромное время для выбора совпадающих строк. Есть ли правильный способ ускорить получение моей базы данных? Я думаю, что индексирование может не работать из-за того, что я не ищу только начальную точку строк. Эти совпадающие слова могут содержаться где угодно в строках. Каков эффективный способ сделать это? Огромное время, затраченное на восстановление. Огромная проблема для меня. Кто-нибудь знает правильный способ сделать это?

+1

См. Индексы FULLTEXT, но обратите внимание, что совпадения совпадений> 50% набора данных не будут возвращены – Strawberry

+0

@Strawberry - это работа на других языках, а не на английском языке? У вас есть правильное руководство об этом? – Maduri

+1

FULLTEXT поддерживает большинство многобайтовых наборов символов. Исключением является то, что для Unicode может использоваться набор символов utf8, но не набор символов ucs2. См. Руководство. – Strawberry

ответ

0

Вам не нужно для цикла, просто сделать так:

sb.append("SELECT Sentence FROM corpus Where Sentence like '%"); 

sb.append(wordList); 

sb.append("%'"); 
+0

Насколько эффективен поиск? Мой запрос создается очень быстро. Проблема остается в прохождении каждой строки и выборе совпадающих строк. – Maduri

0

Я считаю, что эффективным решением является использование PreparedStatement с параметром связывания и выполнить его в петлю. Вы можете использовать For-Each Loop, и для каждого word в wordList связать параметр, а затем получить ResultSet (используя try-with-resources) и добавить возвращенную sentences к вашему List с чем-то вроде

List<String> sentences = new ArrayList<>(); 
String sql = "SELECT Sentence FROM corpus WHERE Sentence LIKE ?"; 
PreparedStatement ps = null; 
try { 
    ps = conn.prepareStatement(sql); 
    for (String word : wordList) { 
     ps.setString(1, String.format("%%%s%%", word)); 
     try (ResultSet rs = ps.executeQuery()) { 
      sentences.add(rs.getString(1)); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} finally { 
    if (ps != null) { 
     try { 
      ps.close(); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

В то время как индекс FULLTEXT на Sentence столбец, вероятно, рекомендуется, этот метод имеет преимущество с использованием кеша запросов и уменьшением размера вашего запроса. Оговорки OR просто грязные, так как вам нужны соответствующие строки любого из них. Вы также можете рассмотреть Set<String> sentences.

+0

Проблема заключается в том, что MySQL не может использовать индексы для поиска по диким картам, где дикая карта предшествует строке. Это решение ничего не делает для решения этого. – Strawberry

+0

@Strawberry Edit добавляет о FULLTEXT индексе, но без этого вы все еще получаете преимущество кеша запросов (и уменьшаете размер запроса). –

+0

@ElliottFrisch Это значит, должен ли я изучать индекс FULLTEXT и добавлять в мою базу данных? – Maduri

Смежные вопросы