2017-07-06 2 views
0

Ich habe Probleme bei der Optimierung einer Suche, die ich in PHP erstellt habe, diese Suche wird nur einmal verwendet, daher ist Flexibilität nicht so wichtig.Optimieren einer Satzsuche über mehrere Dokumente

Ich habe eine Reihe von Sätzen, wie:

$arr = [ 
    'potato', 
    'hi my name is Ivan' 
    .. 
]; 

Das Array etwa 1k Sätze enthält.

Und ich habe eine Festplatte mit 200 GB Dateien.

Ich muss alle Dateien durchsuchen und sehen, ob einige dieser Sätze in den Dateien sind, und wenn ja, den Pfad, eine Prüfsumme usw. in einem bestimmten Format auszudrucken.

Die Frage, die ich bin vor ist die Suchzeit, wenn so etwas wie dies zu tun, was ineffizient scheint: Selbst

$objections = []; 
foreach ($files as $file) { 

    if (!in_array($file->getExtension(), $allowedExt)) 
     continue; 

    $txt = file_get_contents($file); 

    foreach ($words as $word) { 
     if (stripos($txt, $word) !== false || 
      stripos($file->getFilename(), $word) !== false 
      ) { 
      $file->c_md5 = getCMD5($file); 
      $objections[] = $file; 
     } 
    } 
} 

Die Suche ist im Alter von 1 h +, und ich bin an einem neuen MacBook mit dem neuesten i7 unter . Mit PHP Speicher usw. maxed.

Es ist nicht relevant, welches Wort in der Wortgruppe übereinstimmt, also habe ich mich gefragt, ob es eine cleverere Möglichkeit gibt, die Suche durchzuführen, als die Wörter innerhalb der Dateischleife zu durchlaufen. Wäre ein sehr langer REGEX-String mit ODERs schneller?

Oder gibt es einen dritten Weg, der sehr schnell ist.

+0

I don‘ Ich weiß nicht, ob ein großer Regex schneller wäre, aber wenn du eine Idee hast, wie man einen solchen (was du scheinst) zu machen, versuche es einfach und benchmark. Bei dieser Datenmenge wird es wahrscheinlich sehr langsam sein. –

Antwort

0

Definitiv Antwort ist eine Regex. Sie sollten wahrscheinlich in drei Phasen aufgeteilt:

  1. Konvertieren Sie Ihre Liste der Sätze in einer großen regex oder eine Liste von regulären Ausdrücken in einer Schleife ausgeführt werden. Sie können Leerzeichen in Whitespaces \s konvertieren und die Suche un-gierig machen /regex/U.

  2. Iterieren Sie Dateien und entfernen Sie Zeilenenden, indem Sie sie durch Leerzeichen ersetzen. Nur für den Fall, dass ein Satz über mehrere Zeilen verteilt wird.

  3. Verwenden Sie preg_match, um herauszufinden, ob der Satz in der Datei enthalten ist. Sie können es in der Schleife tun, wenn Sie sich für mehrere Regex entscheiden.

+1

Ich denke, wenn du mit Regex gehst, solltest du einen großen Regex haben, sonst wirst du im Grunde nur eine langsamere Art und Weise implementiert, was der ursprüngliche Code bereits tut. Regex ist nicht effizient für einfache String-Vergleiche. (Aber es wird effizienter, wenn Sie nicht jeden Satz in jeder Datei durchlaufen müssen). –

+0

@MagnusEriksson Ich stimme zu, eine große Regex sollte besser sein. –

+0

Ich werde mit einem Regex und Benchmark testen –

0

Ein Regex wird Sie wenig oder nichts sparen.

Sie können bei einem Treffer aus der Schleife ausbrechen.

Foreach{ 
    If(hit){ 
     Break; 
    } 
} 

Was wäre die Suche nach dem Rest sparen. Wenn Sie also auf die zweite Iteration klicken, müssen Sie keine weiteren 998 Iterationen dieses Dokuments durchführen.

Das Problem, das Sie immer haben werden, ist das Öffnen eines Dokuments, das ohne Zweifel die meisten Ihrer Leistung verloren geht.

Wenn es sich um eine Operation handelt, die mehrmals ausgeführt werden muss, ist es wahrscheinlich eine Überlegung wert, alle Ihre Dateien in eine Datenbank für die Volltextsuche ElasticSearch zu indizieren. In Ihrer Datenbank können Sie dann einfach einen Verweis auf die physische Datei für den nächsten Vorgang beibehalten. Das anfängliche Laden und Indexieren all dieser Dateien wird zwar einige große Ressourcen und Zeit beanspruchen.Aber sobald Sie fertig sind, werden Ihre Suchen wirklich schnell sein.

+0

Ah ja, ich habe vergessen, das hinzuzufügen, sind selten tho, aber ja, sollte def einige Zeit sparen –

+0

Dann würde ich ernsthaft in die Implementierung einer Datenbank wie ElasticSearch wie erwähnt suchen. Sie laden bereits alle Dateiinhalte, werfen sie intiba Datenbank wäre trivial, und dann die Suche erfordert ein paar Funktionen. Die Dokumentation für ElasticSearch ist großartig. – Doug

+0

Sogar Volltextsuche auf MySQL könnte schneller sein. –

0

können Sie verwenden exec

eine test.php Datei erstellen und versuchen, diesen Code

<?php 
    exec('grep '.escapeshellarg('end').' '."./test.php",$result);    
    print_r($result); 
    /* serach for some sentences 
    * keep seraching 
    * end of comment */ 
    ?> 

Ofcourse müssen Sie seine Leistung zuerst testen passen Sie es dann auf Ihre Bedürfnisse

Verwandte Themen