È possibile ottimizzare una query di dati principali durante la ricerca di parole corrispondenti in un testo? (Questa domanda riguarda anche la saggezza di SQL personalizzato rispetto a Core Data su un iPhone.)Come ottimizzare la query di dati fondamentali per la ricerca testo completo
Sto lavorando a una nuova app (iPhone) che è uno strumento di riferimento portatile per un database scientifico. L'interfaccia principale è una vista tabella standard ricercabile e voglio una risposta as-you-type mentre l'utente digita le nuove parole. Le corrispondenze di parole devono essere prefissi di parole nel testo. Il testo è composto da 100.000 di parole.
Nel mio prototipo ho codificato direttamente SQL. Ho creato una tabella "parole" separata contenente ogni parola nei campi di testo dell'entità principale. Ho indicizzato le parole e ho eseguito ricerche lungo le linee di
SELECT id, * FROM textTable
JOIN (SELECT DISTINCT textTableId FROM words
WHERE word BETWEEN 'foo' AND 'fooz')
ON id=textTableId
LIMIT 50
Questo funziona molto velocemente. Probabilmente l'utilizzo di un IN funzionerebbe altrettanto bene, ovvero
SELECT * FROM textTable
WHERE id IN (SELECT textTableId FROM words
WHERE word BETWEEN 'foo' AND 'fooz')
LIMIT 50
Il LIMIT è fondamentale e consente di visualizzare i risultati rapidamente. Notifica all'utente che ce ne sono troppi da visualizzare se viene raggiunto il limite. Questo è kludgy.
Ho passato gli ultimi giorni a riflettere sui vantaggi del passaggio a Core Data, ma mi preoccupo della mancanza di controllo nello schema, dell'indicizzazione e dell'interrogazione per una query importante.
In teoria un NSPredicate di textField MATCHES '.*\bfoo.*'
funzionerebbe, ma sono sicuro che sarà lento. Questo tipo di ricerca di testo sembra così comune che mi chiedo quale sia il solito attacco? Vuoi creare un'entità di parole come ho fatto sopra e usare un predicato di "parola BEGINSWITH 'foo'"? Funzionerà così veloce come il mio prototipo? I dati principali creeranno automaticamente gli indici corretti? Non riesco a trovare alcun mezzo esplicito per consigliare lo store persistente sugli indici.
Vedo alcuni vantaggi di Core Data nella mia app per iPhone. Le anomalie e altre considerazioni sulla memoria consentono recuperi di database efficienti per le query tableview senza impostare limiti arbitrari. La gestione del grafo degli oggetti mi consente di attraversare facilmente le entità senza scrivere molto SQL. Le funzionalità di migrazione saranno belle in futuro. D'altra parte, in un ambiente con risorse limitate (iPhone) mi preoccupo che un database generato automaticamente sia gonfio di metadati, relazioni inverse non necessarie, tipi di attributi inefficienti, ecc.
Devo immergermi o procedere con cautela? .
Grazie per la risposta. Sto solo scrivendo lo strumento da riga di comando per caricare i dati sqlite iniziali in un db compatibile con xcdatamodel. Lavoro sostanziale coinvolto. Riferirò sulla mia esperienza. –
Per seguire il tuo esempio, penso che il problema è che una richiesta di recupero non si trova nell'entità di Word, ma nell'entità textTable. (Supponiamo che textTable contenga messaggi di posta elettronica e Word contenga tutte le parole in tutti i campi di posta elettronica.) Penso che questo complichi significativamente la faccenda perché fetchResultsController deve contenere entità textTable filtrate tramite un predicato - e tale predicato ANY o SUBQUERY è lento. Forse c'è un modo per farlo nella direzione "opposta": avviando w/Word corrisponde, seguendo la relazione inversa, e univoca textTable. Hmmm. –
Se la prima parte del predicato riduce lo spazio di ricerca il più possibile, il resto del predicato verrà eseguito più rapidamente, in generale, con meno spazio da cercare all'interno. Dai un'occhiata alla sezione performance della guida Core Data qui: http://developer.apple.com/mac/library/documentation/cocoa/conceptual/CoreData/Articles/cdPerformance.html#//apple_ref/doc/uid/ TP40003468 –