Skip to content

Commit 8ab2dc2

Browse files
committed
Improve scan time for some cases
When the path being matched has a sqlite wildcard character in it, a "like" match will be quite slow. Unfortunately this is fairly common, since "_" is a wildcard character. However, because in most cases the case of the path in the database will match the case on disk, an "=" match will work, so it is worthwhile to try an "=" match first, before trying a "like". If there are no wildcard characters, the "like" will be as fast as the "=", because of the case-insensitive index on the _data column, so there is no need to try "=" first in that case. b/6751354 Change-Id: I1cd4efbd56a37886cb44a86acb73eb9a3c9f303d
1 parent b1758cf commit 8ab2dc2

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

media/java/android/media/MediaScanner.java

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,24 +1463,42 @@ public void scanMtpFile(String path, String volumeName, int objectHandle, int fo
14631463
}
14641464

14651465
FileEntry makeEntryFor(String path) {
1466-
String key = path;
14671466
String where;
14681467
String[] selectionArgs;
1469-
if (mCaseInsensitivePaths) {
1470-
// the 'like' makes it use the index, the 'lower()' makes it correct
1471-
// when the path contains sqlite wildcard characters
1472-
where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
1473-
selectionArgs = new String[] { path };
1474-
} else {
1475-
where = Files.FileColumns.DATA + "=?";
1476-
selectionArgs = new String[] { path };
1477-
}
14781468

14791469
Cursor c = null;
14801470
try {
1471+
boolean hasWildCards = path.contains("_") || path.contains("%");
1472+
1473+
if (hasWildCards || !mCaseInsensitivePaths) {
1474+
// if there are wildcard characters in the path, the "like" match
1475+
// will be slow, and it's worth trying an "=" comparison
1476+
// first, since in most cases the case will match.
1477+
// Also, we shouldn't do a "like" match on case-sensitive filesystems
1478+
where = Files.FileColumns.DATA + "=?";
1479+
selectionArgs = new String[] { path };
1480+
} else {
1481+
// if there are no wildcard characters in the path, then the "like"
1482+
// match will be just as fast as the "=" case, because of the index
1483+
where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
1484+
selectionArgs = new String[] { path };
1485+
}
14811486
c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
14821487
where, selectionArgs, null, null);
1483-
if (c.moveToNext()) {
1488+
if (!c.moveToFirst() && hasWildCards && mCaseInsensitivePaths) {
1489+
// Try again with case-insensitive match. This will be slower, especially
1490+
// if the path contains wildcard characters.
1491+
// The 'like' makes it use the index, the 'lower()' makes it correct
1492+
// when the path contains sqlite wildcard characters,
1493+
where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
1494+
selectionArgs = new String[] { path };
1495+
c.close();
1496+
c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
1497+
where, selectionArgs, null, null);
1498+
// TODO update the path in the db with the correct case so the fast
1499+
// path works next time?
1500+
}
1501+
if (c.moveToFirst()) {
14841502
long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
14851503
int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
14861504
long lastModified = c.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);

0 commit comments

Comments
 (0)