Frage

Ich arbeite an einer Anwendung, die auf Windows Mobile läuft 6, das alle Elemente einer Positionstabelle abrufen zu können, muss die eine bestimmte Zeichenkette enthält (durch den Endverbraucher zur Verfügung gestellt) in dem Feld Beschreibung des Artikels. Das Problem ist, dass es etwa 170.000 Elemente in der Tabelle sind. Da ich alle Einzelteile zurückbringen muß, die die Zeichenfolge überall in der Beschreibung enthalten Ich bin ein LIKE% Zeichenfolge% verwenden gezwungen, das jede Chance eliminiert den Index zu verwenden. Die Daten und Tabellenstruktur auf einer Fortschritt Datenbank ursprünglich zugrunde, die auf ein beliebiges Wort indizierten Feldern eine wunderbare enthält Operator hat. Dies ist nicht der Fall auf unserer mobilen Anwendung, da es SQL Server Compact 3.5 verwendet.

Im Grunde läuft meine DAL die Abfrage und ruft einen SqlCeDataReader und verwendet dann eine ItemFactory ein List-Objekt zu erstellen, die nur die angepassten Elemente enthalten. Das ist offensichtlich können wir halten unsere Domain / Business-Objekte aus der Datenzugriffsschicht zu trennen.

schön und gut, mit Ausnahme der 8m und 42s, die es braucht, Elemente abzurufen, wenn ich für alle Artikel suchen, die so etwas wie „Golf“ in der Beschreibung enthalten. Offensichtlich ist dies kein akzeptabler Zeitrahmen für den Endverbraucher.

Mein erster Versuch, alle Einzelteile zurück aus der Datenbank statt abrufen war mit SELECT * FROM Item“(mit einer ORDER BY-Klausel auf eine der wichtigsten indizierten Felder). Zu diesem Zeitpunkt lief ich eine IndexOf Scheck, als ich durch das lief SqlCeDataReader und hatte die ItemFactory nur Elemente zur Liste Objekt hinzufügen, wenn sie den gewünschten Beschreibungstext enthalten ist. Dadurch wird die Geschwindigkeit auf 1m 46s verbessert hinunter. Nicht schlecht, aber immer noch zu langsam.

Ich habe dann versucht, einen anderen Ansatz, der Versprechen zeigte ... fast ... Während die Anwendung startet, Ich habe versucht, eine Liste erstellen, die alle Artikel Objekte in der Datenbank enthalten sind (dauert ca. 2 Minuten, um die Abfrage auszuführen und die gesamte bevöl Liste, aber zumindest ist es nur einmal als die App ... noch initialisiert ... igitt). Sobald die Liste vollständig ist, kann ich leicht Abfragen auf dieser Liste laufe Dinge wie die folgenden Aktionen (Ich hoffe, meine Syntax richtig ist ... Ich bin nicht bei der Arbeit jetzt und ich habe nicht Visual Studio auf dem PC I ‚sitzt at):

List<Item> specificItems = 
    AllItems.FindAll(i => i.Description.IndexOf(searchString, StringComparison.OrdinalIgnoreCase) >= 0);

Dieser Ansatz klopfte es an 21s nach unten. Sehr schön (noch, obwohl in dem großen Plan der Dinge langsam). Allerdings ist das Problem, dass die Speicherauslastung viel zu groß ist, wenn ich alle Elemente aus der Datenbank laden. Ich musste tatsächlich die letzten 20.000 Artikel abgeschnitten (so der 21s Zeitrahmen wahrscheinlich gewesen wäre, wie 25s) während der Anfangslast, weil ein OutOfMemoryException geworfen wurde. Nach dem Speicher-Manager auf dem Emulator, hatte ich noch etwa 20 MB freien RAM, aber ich habe gehört, dass ein Prozess nur 32 MB oder RAM zugeordnet sein kann (nicht sicher, ob das WM stimmt für 6, aber es scheint, so).

Um sicherzustellen, war es nicht, weil ich ein List-Objekt wurde mit allen Elemente halten (was ich mit der benötigten Kapazität in seinem Konstruktor instanziieren wurde dynamische Größenanpassung zu vermeiden), die ich habe auch kann es zu zusätzlichen Speichern gelesen Verwendung, wenn es implicity EnsureCapacity nennt, habe ich versucht, ein Element [] Array (vor der Zeit bemessen). Dies hatte noch das Speicherproblem und die Größenunterschied war vernachlässigbar.

Ok genug Wanderungen. Ich weiß, ich bin wahrscheinlich einige haben gehen, wie die Datensätze aus der Datenbank, die von der Datareader zurück begrenzen (durch einige indizierte Suche auf einer anderen Art von Feld) und dann wird wahrscheinlich indexOf verwenden, um auf diese kleinere Teilmenge von Elementen maximale Leistung zu erhalten (also das Überspringen der Like-Operator alle zusammen). Dies wird der Endbenutzer dazu führen, mehr als nur eine Beschreibung suchen obwohl eingeben zu müssen (vielleicht Information Hierarchie zu begrenzen, welche Art von Elementen suchen innerhalb).

Irgendwelche Ideen? Bin ich über diese gehen in die falsche Richtung?

Danke für das Hören (sorry Dieser Beitrag ist lang, ich denke Art laut).

Oh, ich soll (nur in Zusammenfassung) hinzufügen, was ich bin mit:

  • Windows Mobile 6
  • SQL Server Compact Edition 3.5
  • C # 3.5

UPDATE: Während der Bloom-Filter-Ansatz unten erwähnte interessant schien, konnte ich nicht eine Anforderung erfüllen (die ich angeben oben nicht wirklich). Ich kann wirklich nicht Worte übereinstimmen, die in anderen Worten enthalten sind (zum Beispiel „Club“ würde nicht zurückkehren „Clubs“). Aus diesem Grunde wurde ich insgesamt einen anderen Ansatz zu verwenden, gezwungen (Kent Fredric ... Vielen Dank für diesen Hinweis). Ich habe Kent Antwort als richtig markiert, da sein Ansatz derjenige war, der die meisten Anforderungen gefüllt (Mitch hatte Ihr ein ähnliches Problem wie die Bloom-Filter von Jaunder vorgeschlagen). Ich habe jedoch einen anderen Ansatz gegangen (jetzt ...) als sein Weg auch.

Was ich getan habe, ist alles Einzelteil gezogen Objekte in dem Speicher mit nur Artikelnummern und Beschreibungen (die es unter den Speicherbeschränkungen halten, aber es ist immer noch eine längere Initialisierung verursacht als Ich mag ... Multithreading und lädt diese Informationen hinter den Kulissen, während die Anwendung ausgeführt wird sich darum kümmern kann ich denke). Um die Suche durchführen ich geschrieben habe meine eigene enthält Routine. Die Routine wird in nicht verwalteten c # Code geschrieben, die zwei Zeiger und ein paar Schleifen verwendet durch die Beschreibung und der erforderlichen passenden Text zu laufen. Wenn es eine Übereinstimmung überall in der Beschreibung findet, fügt es die Positionsnummer in ein Array. Sobald alle Gegenstände durchsucht worden, eine neue Abfrage geht zurück auf die Datenbank und greift nur die passenden Artikelnummern (was aufgrund des Index auf einem Integer-Feld sehr schnell ist). Dann werden diese Elemente in einer Liste mit allen Informationen (nicht nur die Artikelnummer und Beschreibung) erstellt. Der gesamte Vorgang dauert ca. 5 - 10 Sek. (Abhängig von der Beschreibung), die jetzt gut genug ist,

Ich werde sehe immer noch in weiter zu optimieren diese (vielleicht in der Lage sein, wie viele Zeichen zu verfolgen der Suchbegriff ist ... wenn es weniger Zeichen auf der Artikelbeschreibung Rest als der erforderlichen Text könnte die Schleife weiter geradeaus auf dem nächster Punkt).

sind Irgendwelche Vorschläge nach wie vor willkommen. Denn jetzt habe ich Kent Antwort als „die richtigen“ für meine Frage markiert.

Requisiten zu Dolch mir geholfen, schreiben die enthält Routine.

scroll top