Это нормально, что sqlite.fetchall() так медленно?

У меня есть SQL-запрос, который выбирает из двух внутренних объединенных таблиц. Выполнение оператора select занимает около 50 секунд. Однако fetchall() занимает 788 секунд и получает только 981 результат. Это код запроса и выборки:

time0 = time.time()
self.cursor.execute("SELECT spectrum_id, feature_table_id "+
                    "FROM spectrum AS s "+
                    "INNER JOIN feature AS f "+
                    "ON f.msrun_msrun_id = s.msrun_msrun_id "+
                    "INNER JOIN (SELECT feature_feature_table_id, min(rt) AS rtMin, max(rt) AS rtMax, min(mz) AS mzMin, max(mz) as mzMax "+
                                 "FROM convexhull GROUP BY feature_feature_table_id) AS t "+
                    "ON t.feature_feature_table_id = f.feature_table_id "+
                    "WHERE s.msrun_msrun_id = ? "+
                    "AND s.scan_start_time >= t.rtMin "+
                    "AND s.scan_start_time <= t.rtMax "+
                    "AND base_peak_mz >= t.mzMin "+
                    "AND base_peak_mz <= t.mzMax", spectrumFeature_InputValues)
print 'query took:',time.time()-time0,'seconds'

time0 = time.time()
spectrumAndFeature_ids = self.cursor.fetchall()      
print time.time()-time0,'seconds since to fetchall'

Есть ли причина, по которой сборка занимает так много времени?


Обновить

Выполнение:

while 1:
    info = self.cursor.fetchone()
    if info:
        <do something>
    else:
        break

идет так же медленно, как

allInfo = self.cursor.fetchall()         
for info in allInfo:
    <do something>

2 ответа

Решение

По умолчанию fetchall() так медленно, как зацикливание fetchone() из-за arraysize из Cursor объект устанавливается на 1.

Чтобы ускорить процесс вы можете зациклить fetchmany(), но чтобы увидеть прирост производительности, вам нужно предоставить ему параметр размера больше 1, иначе он получит "много" партиями arraysizeт.е.

Вполне возможно, что вы можете получить прирост производительности, просто увеличив значение arraysize, но у меня нет опыта в этом, поэтому вы можете поэкспериментировать с этим, выполнив что-то вроде:

>>> import sqlite3
>>> conn = sqlite3.connect(":memory:")
>>> cu = conn.cursor()
>>> cu.arraysize
1
>>> cu.arraysize = 10
>>> cu.arraysize
10

Подробнее об этом здесь: http://docs.python.org/library/sqlite3.html

Если вы выполняете сложный запрос, попробуйте создать таблицу, используя этот сложный запрос, а затем выполните выборку в созданной таблице, чтобы производительность была хорошей.

Другие вопросы по тегам