2015-09-22 5 views
1

У меня есть очень простой индекс с двумя полями - поле с числовым идентификатором и поле с длиной от 60 до 100 символов. Строковое поле содержит последовательности ДНК, без пробелов.Не удается решить узкое место в поиске Lucene.net на Azure

Так, например, заданное значение поля: AATCTAGATACGAGATCGATCGATCGATCGATCGATCGATGCTAGC

и SearchString будет что-то вроде: GATCGATCGA

Есть более 7 миллиона строк, а индекс приходит примерно 1 Гб.

Я сохраняю индекс в хранилище azure blob и запускаю простое веб-приложение, которое запрашивает индекс в экземпляре веб-приложения B1.

Независимо от размера строки поиска, я не могу заставить операцию работать быстрее, чем 20-21 секунд.

Я пробовал масштабирование до экземпляра B3, но все же он входил через 20 секунд.

Я выделил узкое место , когда запрос выполняется против IndexSearcher.

Чтобы найти, я прикрепляю шаблон к началу и концу строки поиска.

Мой код выглядит следующим образом

var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30); 
    var parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "nucleotide", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30)); 
    parser.AllowLeadingWildcard = true; 
    var storageAccount = CloudStorageAccount.Parse("connection info"); 
    var azureDir = new AzureDirectory(storageAccount, "myindex", new RAMDirectory()); 
    IndexSearcher searcher = new IndexSearcher(azureDir, true); 
var query = parser.Parse("*" + mystring + "*");  
TopDocs hits = searcher.Search(query, 50); 
+1

Ваш поиск '* term *' требует полной итерации всех терминов, которые будут выполняться навсегда. Я предполагаю, что у вас много условий. Не могли бы вы разбить его при индексировании на GA + TC + ... и затем искать те, которые используют позиционную информацию? (Как phraseQuery) – sisve

+1

Я знаю, что я знаю, но начать поиск с дикой карты будет медленным. Это все равно 350/миллисекунда, и ему нужно прикоснуться к каждой строке, что неплохо. Может быть, попробуйте карту в байт и регулярное выражение, но все еще не уверены, что бьет 350/миллисекунда. – Paparazzi

+0

'* x *' всегда будет медленным поиском. Я очень впечатлен, что это так быстро, учитывая. –

ответ

0

Не на всех в ответ Lucene
После того, как вы видели это просто комментарий, и я буду удалять его
Но это было бы SQL Раствора

Table 
int32 seqID 
tinyint pos 
char(1) value 

with the first two as a composite PK 

, то вы только что создали запрос

select distinct t1.seqID 
    from table t1 
    join table t2 
      on t2.seqID = t1.seqID 
     and t2.pos = t1.pos + 1 
     and t1.val = 'val1' 
     and t2.val = 'val2' 
    join table t3 
      on t3.seqID = t1.seqID 
     and t3.pos = t1.pos + 2 
     and t3.val = 'val3' 
    join table t4 
      on t4.seqID = t1.seqID 
     and t4.pos = t1.pos + 3 
     and t4.val = 'val4' 
    ... 

Я знаю, что может выглядеть сумасшедшим, но SQL имеет индекс для всех этих объединений и должен фильтровать раньше (не касаться всех строк). Да, он касается всех строк, но с помощью символа char char и должен сдаваться, как только char by char терпит неудачу.

Как я уже сказал в комментарии, я бы тоже попробовал грубое силовое регулярное выражение, но я сомневаюсь, что он будет бить 350/мс, поскольку он должен касаться всех строк. И вы не могли сопоставить байту, как я сказал в комментарии, поскольку регулярное выражение представляет собой текстовый поиск.

К другому варианту относится класс ДНК, который использует массив байтов внутри с методом Like, который сравнивает байты, но я также сомневаюсь, что будет бить 350/мс.
byte array pattern match