В sqlite с версии 3.8 появился partial index — возможность строить индекс по заданному условию.
CREATE INDEX temperature_scale_1 ON temperature(sensor ASC, timestamp ASC) WHERE scale=1;
CREATE INDEX temperature_scale_5 ON temperature(sensor ASC, timestamp ASC) WHERE scale=5;
Но при запуске prepared statement планировщик выбирает индексы ДО байндинга, а значит ещё не знает, каким будет значение условия, и созданный partial index использован не будет.
Приходится вручную подставлять значения, используемые таким индексом, и снова помнить про экранирование от sql-инъекций, если используются не числовые значения.
sensor, scale, start, end = 1, 5, 1451628000, 1452492000
c.execute('SELECT * FROM temperature WHERE sensor = ? AND scale = %d AND timestamp BETWEEN ? AND ?' % (scale), (sensor, start, end))