Index: bin/migration/migrate_0.97_0.98.py
===================================================================
--- bin/migration/migrate_0.97_0.98.py	(revision 79778c501f7f970a2e3b50eaca4fe0f14c167623)
+++ bin/migration/migrate_0.97_0.98.py	(revision 6b4092ba00ad78668db6d6fcf6fc656ded39f705)
@@ -353,4 +353,20 @@
         root['RoomBlocking']['Indexes']['RoomBlockings'] = OOBTree()
 
+@since('0.98b2')
+def runRoomDayIndexInit(dbi, withRBDB, prevVersion):
+    """
+    Initializing room+day => reservation index.
+    """
+    if not withRBDB:
+        return
+
+    root = DALManager().getRoot()
+    if not root.has_key('RoomDayReservationsIndex'):
+        root['RoomDayReservationsIndex'] = OOBTree()
+        for i, resv in enumerate(CrossLocationQueries.getReservations()):
+            resv._addToRoomDayReservationsIndex()
+            if i % 1000 == 0:
+                DALManager.commit()
+    DALManager.commit()
 
 @since('0.98b2')
Index: indico/MaKaC/plugins/RoomBooking/default/dalManager.py
===================================================================
--- indico/MaKaC/plugins/RoomBooking/default/dalManager.py	(revision 8ae4b3d3d737358d48062a83ed2f340c8428856d)
+++ indico/MaKaC/plugins/RoomBooking/default/dalManager.py	(revision 6b4092ba00ad78668db6d6fcf6fc656ded39f705)
@@ -88,5 +88,5 @@
                     self.root[name] = IOBTree()
                 elif name in ["RoomReservationsIndex", "UserReservationsIndex",
-                              "DayReservationsIndex"]:
+                              "DayReservationsIndex", "RoomDayReservationsIndex"]:
                     self.root[name] = OOBTree()
                 elif name in ["EquipmentList", "CustomAttributesList"]:
Index: indico/MaKaC/plugins/RoomBooking/default/initialize.py
===================================================================
--- indico/MaKaC/plugins/RoomBooking/default/initialize.py	(revision 18c3cbdcb9077974d1a18146082097abdc760cda)
+++ indico/MaKaC/plugins/RoomBooking/default/initialize.py	(revision 6b4092ba00ad78668db6d6fcf6fc656ded39f705)
@@ -133,4 +133,6 @@
     if force or not root.has_key( 'DayReservationsIndex' ):
         root['DayReservationsIndex'] = OOBTree()
+    if force or not root.has_key( 'RoomDayReservationsIndex' ):
+        root['RoomDayReservationsIndex'] = OOBTree()
 
     # Create possible equipment branch
Index: indico/MaKaC/plugins/RoomBooking/default/reservation.py
===================================================================
--- indico/MaKaC/plugins/RoomBooking/default/reservation.py	(revision 7e6678add41d513fe717dee95c9645a16ab88f73)
+++ indico/MaKaC/plugins/RoomBooking/default/reservation.py	(revision 6b4092ba00ad78668db6d6fcf6fc656ded39f705)
@@ -19,4 +19,5 @@
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
+from BTrees.OOBTree import OOSet
 from ZODB import FileStorage, DB
 from ZODB.DB import DB, transaction
@@ -43,4 +44,5 @@
 _USER_RESERVATIONS_INDEX = 'UserReservationsIndex'
 _DAY_RESERVATIONS_INDEX = 'DayReservationsIndex'
+_ROOM_DAY_RESERVATIONS_INDEX = 'RoomDayReservationsIndex'
 
 class Reservation( Persistent, ReservationBase, Observable ):
@@ -89,4 +91,8 @@
     def getDayReservationsIndexRoot( ):
         return Reservation.__dalManager.getRoot(_DAY_RESERVATIONS_INDEX)
+
+    @staticmethod
+    def getRoomDayReservationsIndexRoot():
+        return Reservation.__dalManager.getRoot(_ROOM_DAY_RESERVATIONS_INDEX)
 
     def insert( self ):
@@ -131,4 +137,7 @@
         self._addToDayReservationsIndex()
 
+        # Update room+day => reservations index
+        self._addToRoomDayReservationsIndex()
+
         self._notify('reservationCreated')
 
@@ -157,8 +166,10 @@
     def indexDayReservations( self ):
         self._addToDayReservationsIndex()
+        self._addToRoomDayReservationsIndex()
         self._p_changed = True
 
     def unindexDayReservations( self ):
         self._removeFromDayReservationsIndex()
+        self._removeFromRoomDayReservationsIndex()
         self._p_changed = True
 
@@ -182,4 +193,6 @@
         # Update day => reservations index
         self._removeFromDayReservationsIndex()
+        # Update room+day => reservations index
+        self._removeFromRoomDayReservationsIndex()
 
         self._notify('reservationDeleted')
@@ -210,4 +223,27 @@
                 dayReservationsIndexBTree[day] = resvs
 
+    def _addToRoomDayReservationsIndex(self):
+        roomDayReservationsIndexBTree = Reservation.getRoomDayReservationsIndexRoot()
+
+        for period in self.splitToPeriods():
+            day = period.startDT.date()
+            key = (self.room.id, day)
+            resvs = roomDayReservationsIndexBTree.get(key)
+            if resvs is None:
+                resvs = OOSet()
+            resvs.add(self)
+            roomDayReservationsIndexBTree[key] = resvs
+
+    def _removeFromRoomDayReservationsIndex(self):
+        roomDayReservationsIndexBTree = Reservation.getRoomDayReservationsIndexRoot()
+
+        for period in self.splitToPeriods():
+            day = period.startDT.date()
+            key = (self.room.id, day)
+            resvs = roomDayReservationsIndexBTree.get(key)
+            if resvs is not None and self in resvs:
+                resvs.remove(self)
+                roomDayReservationsIndexBTree[key] = resvs
+
     @staticmethod
     def getReservations( *args, **kwargs ):
@@ -233,7 +269,8 @@
 
         alreadyRoomFiltered = False
-        if rooms and len( rooms ) <= 10:
+        # If we filter by room but not by day, we can use the RoomReservations index
+        if rooms and not days and len(rooms) <= 10:
             # Use room => room reservations index
-            resvCandidates = []
+            resvCandidates = set()
             for room in rooms:
                 if location != None and room.locationName != location:
@@ -241,31 +278,37 @@
                 roomResvs = Reservation.getRoomReservationsIndexRoot().get( room.id )
                 if roomResvs != None:
-                    resvCandidates += roomResvs
+                    resvCandidates.update(roomResvs)
             alreadyRoomFiltered = True
 
+        # If we don't have reservations yet but filter by creator, use the UserReservations index
         if resvCandidates == None and resvEx != None and resvEx.createdBy != None:
-            resvCandidates = Reservation.getUserReservationsIndexRoot().get( resvEx.createdBy )
-            if resvCandidates == None:
-                resvCandidates = []
-
-        if days:
-            resvsInDays = {}
+            resvCandidates = set(Reservation.getUserReservationsIndexRoot().get(resvEx.createdBy, []))
+
+        # If we want to filter by day, we can choose indexes.
+        dayFilteredResvs = None
+        if days and rooms:
+            # If there's a room filter, too - use the RoomDayReservations index
+            dayFilteredResvs = set()
+            for key in ((room.id, day) for day in days for room in rooms):
+                dayRoomResvs = Reservation.getRoomDayReservationsIndexRoot().get(key, [])
+                dayFilteredResvs.update(dayRoomResvs)
+            alreadyRoomFiltered = True
+        elif days:
+            # If we only filter by days, use the DayReservations index
+            dayFilteredResvs = set()
             for day in days:
-                dayResvs = Reservation.getDayReservationsIndexRoot().get( day )
-
-                if dayResvs:
-                    for resv in dayResvs:
-                        resvsInDays[resv] = None
-            if resvCandidates == None:
-                resvCandidates = resvsInDays.iterkeys()
+                dayResvs = Reservation.getDayReservationsIndexRoot().get(day, [])
+                dayFilteredResvs.update(dayResvs)
+
+        # If we have some day-filtered reservations, use that list or restrict the existing one
+        if dayFilteredResvs is not None:
+            if resvCandidates is None:
+                resvCandidates = dayFilteredResvs
             else:
                 # Intersection
-                new = []
-                for resv in resvCandidates:
-                    if resvsInDays.has_key( resv ):
-                        new.append( resv )
-                resvCandidates = new
-
-        if resvCandidates == None:
+                resvCandidates = dayFilteredResvs & resvCandidates
+
+        # If we still have nothing, get all reservations and filter them later in the loop (slow!)
+        if resvCandidates is None:
             resvCandidates = Reservation.getReservationsRoot().itervalues()
 
