Bug 381795 places indexes need review (r=sspitzer, r=marco)

This commit is contained in:
dietrich@mozilla.com 2007-11-20 10:23:38 -08:00
Родитель 8c0a4e55f2
Коммит 07e7930dfb
4 изменённых файлов: 124 добавлений и 133 удалений

Просмотреть файл

@ -108,58 +108,58 @@ AddToHistoryCB(const nsCSubstring &aRowID,
if (columnIndexes[i] != -1) {
values[i] = (*aValues)[columnIndexes[i]];
reader->NormalizeValue(values[i]);
if (i == kHiddenColumn && values[i].EqualsLiteral("1"))
return PL_DHASH_NEXT; // Do not import hidden records.
}
}
// title is really a UTF-16 string at this point
nsCString &titleC = values[kNameColumn];
PRUint32 titleLength;
const char *titleBytes;
if (titleC.IsEmpty()) {
titleBytes = "\0";
titleLength = 0;
} else {
titleLength = titleC.Length() / 2;
// add an extra null byte onto the end, so that the buffer ends
// with a complete unicode null character.
titleC.Append('\0');
// Swap the bytes in the unicode characters if necessary.
if (data->swapBytes) {
SwapBytes(reinterpret_cast<PRUnichar*>(titleC.BeginWriting()));
}
titleBytes = titleC.get();
}
const PRUnichar *title = reinterpret_cast<const PRUnichar*>(titleBytes);
PRInt32 err;
PRInt32 count = values[kVisitCountColumn].ToInteger(&err);
if (err != 0 || count == 0) {
count = 1;
}
PRTime date;
if (PR_sscanf(values[kLastVisitColumn].get(), "%lld", &date) != 1) {
date = -1;
}
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), values[kURLColumn]);
if (uri) {
// title is really a UTF-16 string at this point
nsCString &titleC = values[kNameColumn];
PRUint32 titleLength;
const char *titleBytes;
if (titleC.IsEmpty()) {
titleBytes = "\0";
titleLength = 0;
} else {
titleLength = titleC.Length() / 2;
// add an extra null byte onto the end, so that the buffer ends
// with a complete unicode null character.
titleC.Append('\0');
// Swap the bytes in the unicode characters if necessary.
if (data->swapBytes) {
SwapBytes(reinterpret_cast<PRUnichar*>(titleC.BeginWriting()));
}
titleBytes = titleC.get();
}
const PRUnichar *title = reinterpret_cast<const PRUnichar*>(titleBytes);
PRInt32 err;
PRInt32 count = values[kVisitCountColumn].ToInteger(&err);
if (err != 0 || count == 0) {
count = 1;
}
PRTime date;
if (PR_sscanf(values[kLastVisitColumn].get(), "%lld", &date) != 1) {
date = -1;
}
PRBool isTyped = values[kTypedColumn].EqualsLiteral("1");
PRInt32 transition = isTyped ?
(PRInt32) nsINavHistoryService::TRANSITION_TYPED
: (PRInt32) nsINavHistoryService::TRANSITION_LINK;
nsNavHistory *history = data->history;
history->AddPageWithVisit(uri,
nsDependentString(title, titleLength),
values[kHiddenColumn].EqualsLiteral("1"),
isTyped, count, transition, date);
history->AddPageWithVisit(uri, nsDependentString(title, titleLength),
PR_FALSE, isTyped, count, transition, date);
}
return PL_DHASH_NEXT;
}
@ -237,10 +237,6 @@ nsNavHistory::ImportHistory(nsIFile* aFile)
reader.EnumerateRows(AddToHistoryCB, &data);
// Make sure we don't have any duplicate items in the database.
rv = RemoveDuplicateURIs();
NS_ENSURE_SUCCESS(rv, rv);
#ifdef IN_MEMORY_LINKS
memTransaction.Commit();
#endif

Просмотреть файл

@ -346,15 +346,17 @@ nsNavBookmarks::InitTables(mozIStorageConnection* aDBConn)
"lastModified INTEGER)"));
NS_ENSURE_SUCCESS(rv, rv);
// this index will make it faster to determine if a given item is
// bookmarked (used by history queries and vacuuming, for example)
// This index will make it faster to determine if a given item is
// bookmarked (used by history queries and vacuuming, for example).
// Making it compound with "type" speeds up type-differentiation
// queries, such as expiration and search.
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_bookmarks_itemindex ON moz_bookmarks (fk)"));
"CREATE INDEX moz_bookmarks_itemindex ON moz_bookmarks (fk,type)"));
NS_ENSURE_SUCCESS(rv, rv);
// the most common operation is to find the children given a parent
// The most common operation is to find the children given a parent and position.
rv = aDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_bookmarks_parentindex ON moz_bookmarks (parent)"));
"CREATE INDEX moz_bookmarks_parentindex ON moz_bookmarks (parent,position)"));
NS_ENSURE_SUCCESS(rv, rv);
}

Просмотреть файл

@ -391,10 +391,6 @@ nsNavHistory::Init()
NS_ENSURE_TRUE(mRecentBookmark.Init(128), NS_ERROR_OUT_OF_MEMORY);
NS_ENSURE_TRUE(mRecentRedirects.Init(128), NS_ERROR_OUT_OF_MEMORY);
rv = CreateLookupIndexes();
if (NS_FAILED(rv))
return rv;
// The AddObserver calls must be the last lines in this function, because
// this function may fail, and thus, this object would be not completely
// initialized), but the observerservice would still keep a reference to us
@ -681,20 +677,24 @@ nsNavHistory::InitDB(PRBool *aDoImport)
"favicon_id INTEGER)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_places_urlindex ON moz_places (url)"));
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE UNIQUE INDEX moz_places_url_uniqueindex ON moz_places (url)"));
NS_ENSURE_SUCCESS(rv, rv);
// This index is used for favicon expiration, see nsNavHistoryExpire::ExpireItems.
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_places_faviconindex ON moz_places (favicon_id)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_places_hostindex ON moz_places (rev_host)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_places_visitcount ON moz_places (visit_count)"));
NS_ENSURE_SUCCESS(rv, rv);
}
// FIXME: this should be moved inside the moz_places table creation block.
// It is left outside and the return value is ignored because alpha 1 did not
// have this index. When it is likely that all alpha users have run a more
// recent build, we can move this to only happen on init so that startup time
// is faster. This index is used for favicon expiration, see
// nsNavHistoryExpire::ExpireItems
mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_places_faviconindex ON moz_places (favicon_id)"));
// moz_historyvisits
rv = mDBConn->TableExists(NS_LITERAL_CSTRING("moz_historyvisits"), &tableExists);
NS_ENSURE_SUCCESS(rv, rv);
@ -708,20 +708,21 @@ nsNavHistory::InitDB(PRBool *aDoImport)
"session INTEGER)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_historyvisits_pageindex ON moz_historyvisits (place_id)"));
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_historyvisits_pageindex ON moz_historyvisits (place_id)"));
NS_ENSURE_SUCCESS(rv, rv);
// This makes a big difference in startup time for large profiles because of
// finding bookmark redirects using the referring page.
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_historyvisits_fromindex ON moz_historyvisits (from_visit)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_historyvisits_dateindex ON moz_historyvisits (visit_date)"));
NS_ENSURE_SUCCESS(rv, rv);
}
// This must be outside of the visit creation above because the alpha1 shipped
// without this index. This makes a big difference in startup time for
// large profiles because of finding bookmark redirects using the referring
// page. For final release, if we think everybody running alpha1 has run
// alpha2 or later, we can put it in the if statement above for faster
// startup time (same as above for the moz_places_faviconindex)
mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_historyvisits_fromindex ON moz_historyvisits (from_visit)"));
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
@ -835,7 +836,7 @@ nsNavHistory::InitStatements()
// mDBAddNewPage (see InternalAddNewPage)
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"INSERT INTO moz_places "
"INSERT OR REPLACE INTO moz_places "
"(url, title, rev_host, hidden, typed, visit_count) "
"VALUES (?1, ?2, ?3, ?4, ?5, ?6)"),
getter_AddRefs(mDBAddNewPage));
@ -1039,12 +1040,16 @@ nsNavHistory::CleanUpOnQuit()
NS_LITERAL_CSTRING("DROP INDEX IF EXISTS moz_places_visitcount"));
NS_ENSURE_SUCCESS(rv, rv);
// 2. rename moz_places to moz_places_backup
// 2. remove any duplicate URIs
rv = RemoveDuplicateURIs();
NS_ENSURE_SUCCESS(rv, rv);
// 3. rename moz_places to moz_places_backup
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("ALTER TABLE moz_places RENAME TO moz_places_backup"));
NS_ENSURE_SUCCESS(rv, rv);
// 3. create moz_places w/o user_title
// 4. create moz_places w/o user_title
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("CREATE TABLE moz_places ("
"id INTEGER PRIMARY KEY, "
"url LONGVARCHAR, "
@ -1056,14 +1061,11 @@ nsNavHistory::CleanUpOnQuit()
"favicon_id INTEGER)"));
NS_ENSURE_SUCCESS(rv, rv);
// 4. recreate the indexes
// 5. recreate the indexes
// NOTE: tests showed that it's faster to create the indexes prior to filling
// the table than it is to add them afterwards.
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_places_urlindex ON moz_places (url)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_places_titleindex ON moz_places (title)"));
NS_LITERAL_CSTRING("CREATE UNIQUE INDEX moz_places_url_uniqueindex ON moz_places (url)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_places_faviconindex ON moz_places (favicon_id)"));
@ -1075,14 +1077,14 @@ nsNavHistory::CleanUpOnQuit()
NS_LITERAL_CSTRING("CREATE INDEX moz_places_visitcount ON moz_places (visit_count)"));
NS_ENSURE_SUCCESS(rv, rv);
// 5. copy all data into moz_places
// 6. copy all data into moz_places
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO moz_places "
"SELECT id, url, title, rev_host, visit_count, hidden, typed, favicon_id "
"FROM moz_places_backup"));
NS_ENSURE_SUCCESS(rv, rv);
// 6. drop moz_places_backup
// 7. drop moz_places_backup
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"DROP TABLE moz_places_backup"));
NS_ENSURE_SUCCESS(rv, rv);
@ -1117,6 +1119,11 @@ nsNavHistory::InitMemDB()
NS_LITERAL_CSTRING("CREATE TABLE moz_memhistory (url LONGVARCHAR UNIQUE)"));
NS_ENSURE_SUCCESS(rv, rv);
// In-memory links indexes
rv = mMemDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_memhistory_index ON moz_memhistory (url)"));
NS_ENSURE_SUCCESS(rv, rv);
// prepackaged statements
rv = mMemDBConn->CreateStatement(
NS_LITERAL_CSTRING("SELECT url FROM moz_memhistory WHERE url = ?1"),
@ -1197,7 +1204,8 @@ nsNavHistory::GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
// nsNavHistory::InternalAddNewPage
//
// Adds a new page to the DB. THIS SHOULD BE THE ONLY PLACE NEW ROWS ARE
// Adds a new page to the DB.
// THIS SHOULD BE THE ONLY PLACE NEW moz_places ROWS ARE
// CREATED. This allows us to maintain better consistency.
//
// If non-null, the new page ID will be placed into aPageID.
@ -3394,8 +3402,32 @@ nsNavHistory::OnIdle()
}
// If we've been idle for more than VACUUM_IDLE_TIME_IN_MSECS
// perform a vacuum.
// perform long-idle tasks.
if (idleTime > VACUUM_IDLE_TIME_IN_MSECS) {
// Do a one-time re-creation of the moz_places.url index (bug 381795)
// XXX REMOVE ME AFTER BETA2.
PRBool oldIndexExists = PR_FALSE;
rv = mDBConn->IndexExists(NS_LITERAL_CSTRING("moz_places_urlindex"), &oldIndexExists);
if (oldIndexExists) {
// wrap in an exclusive transaction for safety and performance
mozStorageTransaction urlindexTransaction(
mDBConn, PR_FALSE, mozIStorageConnection::TRANSACTION_EXCLUSIVE);
// drop old index
PRTime start = PR_Now();
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("DROP INDEX IF EXISTS moz_places_urlindex"));
NS_ENSURE_SUCCESS(rv, rv);
// remove any duplicates
rv = RemoveDuplicateURIs();
NS_ENSURE_SUCCESS(rv, rv);
// create new index
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE UNIQUE INDEX moz_places_url_uniqueindex ON moz_places (url)"));
NS_ENSURE_SUCCESS(rv, rv);
rv = urlindexTransaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
}
#if 0
// Currently commented out because vacuum is very slow
// see bug #390244 for more details.
@ -4881,7 +4913,8 @@ nsNavHistory::SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle)
rv = dbModStatement->Execute();
NS_ENSURE_SUCCESS(rv, rv);
transaction.Commit();
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
// observers (have to check first if it's bookmarked)
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
@ -4891,48 +4924,6 @@ nsNavHistory::SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle)
}
// nsNavHistory::CreateLookupIndexes
//
// This creates some indexes on the history tables which are expensive to
// update when we're doing many insertions, as with history import. Instead,
// we defer creation of the index until import is finished.
//
// FIXME: We should check if the index exists (bug 327317) and then not
// try to create it. That way we can check for errors. Currently we ignore
// errors since the indeices may already exist.
nsresult
nsNavHistory::CreateLookupIndexes()
{
nsresult rv;
// History table indexes
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_places_hostindex ON moz_places (rev_host)"));
//NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_places_visitcount ON moz_places (visit_count)"));
//NS_ENSURE_SUCCESS(rv, rv);
// Visit table indexes
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_historyvisits_fromindex ON moz_historyvisits (from_visit)"));
//NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_historyvisits_dateindex ON moz_historyvisits (visit_date)"));
//NS_ENSURE_SUCCESS(rv, rv);
#ifdef IN_MEMORY_LINKS
// In-memory links indexes
rv = mMemDBConn->ExecuteSimpleSQL(
NS_LITERAL_CSTRING("CREATE INDEX moz_memhistory_index ON moz_memhistory (url)"));
NS_ENSURE_SUCCESS(rv, rv);
#endif
return NS_OK;
}
nsresult
nsNavHistory::AddPageWithVisit(nsIURI *aURI,
const nsString &aTitle,

Просмотреть файл

@ -323,6 +323,12 @@ public:
// It is an error to call this method if aURI might already be in history.
// The given aVisitCount should include the given last-visit date.
// aLastVisitDate can be -1 if there is no last visit date to record.
//
// NOTE: This will *replace* existing records for a given URI, creating a
// new place id, and breaking all existing relationships with for that
// id, eg: bookmarks, annotations, tags, etc. This is only for use by
// the import of history.dat on first-run of Places, which currently occurs
// if no places.sqlite file previously exists.
nsresult AddPageWithVisit(nsIURI *aURI,
const nsString &aTitle,
PRBool aHidden, PRBool aTyped,
@ -607,10 +613,6 @@ protected:
nsCOMArray<nsNavHistoryQuery>* aQueries,
nsNavHistoryQueryOptions* aOptions);
// creates supplemental indexes that we'd like to not bother with
// updating during import.
nsresult CreateLookupIndexes();
nsCOMPtr<nsITimer> mIdleTimer;
static void IdleTimerCallback(nsITimer* aTimer, void* aClosure);
nsresult OnIdle();