2014-01-07 1 views
2

Здравствуйте, и новый год,SQLite и проблема с производительностью с SELECT total (value)

Мы по-прежнему боремся с нашим применением моделирования. Особенно при использовании SQLite в качестве таблицы поиска в режиме реального времени во время работы.

Позвольте мне показать вам дизайн таблицы первой: SQLfiddle - Link

Здесь вы можете увидеть таблицу 'TESTTABLE' с:

  1. 'ид' (целое число): в качестве первичного ключа
  2. 'time_abs' (integer): представляет временную метку, связанную с синхронизацией моделирования.
  3. 'r_m' (double): обозначает 'массовый расход' (единица измерения кг/с, например) некоторого расхода
  4. «T_r» (двойной): означает «температура массового расхода»
  5. «тип» (varchar): обозначает вид массового расхода (например, вода)
  6. 'х0' (VARCHAR): представляет собой отход от массового потока (например, сосуд # 1)
  7. 'x1' (VARCHAR): представляет собой место назначения потока массы (например, сосуд # 2)

(на самом деле есть еще некоторые химические и физические свойства, записанные в эту таблицу)

моделирование создает эти данные, и написано с Java методов в базу данных, которая работает довольно хорошо (несколько 10к/с возможно).

Этот вопрос:

Во время моделирования работы двигателя моделирования когда-то нуждается в определенной информации, как «Какова общая масса в vessel1 во время 14?» Мы получаем эту информацию с запросом, как это:


SELECT total(r_m) FROM testtable WHERE time_abs<=14 AND x1='vessel2') - (SELECT total(r_m) FROM testtable WHERE time_abs<=14 AND x0='vessel2'); (, которая: добавление все ставки дохода и вычитая все ставки исходов в одной локальной точке)


, который работает нормально в начале. Но в итоге у нас около 8-10 миллионов строк в этой таблице, и производительность сильно падает. Например. этот запрос занимает почти 6 секунд (3-4 секунды с мангистом SQLite в firefox).

Также в конце мы хотели бы построить общую массу за период 1000 единиц времени (time_abs) с этим запросом, который понадобится около 1000 * 6 секунд. Очевидно, много.

Итак, вопрос в том, что мы можем сделать, чтобы значительно увеличить производительность?

+0

вам нужно только последние 14 временную метку? – PeterRing

+0

Не все «time_abs» меньше, чем «время поиска». Кроме того, timestamp 'time_abs' не уникален из-за одновременных процессов. Поэтому в примере запроса один не может сказать, сколько запросов времени запрошено, так как количество параллельных процессов является переменной. – StefanOverFlow

+0

(по «параллельным процессам». Я имею в виду процессы в моделированном процессе, которые не одновременно обращаются к SQLite, только для уточнения). – StefanOverFlow

ответ

1

Может помочь вам, если вы используете один или несколько дополнительных поля (ы), где вы обновляете/увеличиваем требуемое значение

eg. total_rm or total_diff 

Тогда вам не нужно всего(), но вы можете получить доступ к значение непосредственно с

SELECT total_rm FROM testtable WHERE time_abs=14 AND x1='vessel2') 

Конечно, вы должны создать индекс за time_abs.

+0

Итак, этот запрос такой же, как «SELECT r_m из testtable WHERE time_abs = 14 AND x1 = 'vessel2'", правильно? Просто чтобы проверить эффективность выбора, я попробовал этот запрос в таблице из 10 миллионов строк, и это занимает около 4-5 секунд. Насколько мне известно, проблема в том, что я не использую первичный ключ. И «time_abs», и «x1» не уникальны. Например, если я запрашиваю с аддоном «где id = 15» (например, он принимает только 1 мс). – StefanOverFlow

+0

и что мешает вам создать индекс за time_abs? – sqlab

+0

нет необходимости, чтобы индекс был уникальным. Это просто сокращает доступ, вместо того, чтобы читать все строки поочередно, программа db просто считывает сначала индекс, а затем напрямую ищет строки (ы) – sqlab

1

Возможности:

  1. Предварительно рассчитать требуемый результат. Итак, когда вы вставляете сырые данные, обновите строку в таблице «итоговые». Каждая строка имитирует ваш запрос, обновляя его на основе time_abs и судна. Таким образом, таблица может иметь столбец:

    time_abs, судно, running_total

    Вы обновить running_total с новым значением, основанным на time_abs и судами

  2. вхолостую необработанной обработку данных для более способного сервера. Таким образом, на каждом n вставке необработанных данных загружайте эти данные на более способный сервер с помощью веб-служб. Попросите эту машину вычислить ваши результаты в реальном времени. Как только вставка данных завершена (конец сбора данных), ваши результаты, теоретически, готовы к возврату на Android (снова через веб-службы или аналогичные).

+0

Wrt to option 1: Я думаю, это похоже на то, что ответил sqlab, но с другой таблицей (пожалуйста, поправьте меня, если я ошибаюсь здесь). Здесь также не используется первичный ключ? Wrt to option 2: мы не можем использовать дополнительное оборудование, так как приложение моделирования должно быть автономным и бесплатным. – StefanOverFlow

+0

Они ключевое - это «предварительно вычислить» результат (через концепцию итогов), как ваш ход. Реализовать на основе «наилучшей практики». – robnick

+0

Да, я думаю, вы и sqlab определенно правы. Общая (xyz) -концепция не будет работать. – StefanOverFlow

1

Данный запрос может быть сделан более эффективным с помощью следующих показателей:

CREATE INDEX i_ir ON testtable(x1, time_abs, r_m); 
CREATE INDEX i_or ON testtable(x0, time_abs, r_m); 
+0

Спасибо. Это действительно намного быстрее, но все же недостаточно быстро. Для вывода SELECT total (r_m) sillt требуется >> 1 секунда. – StefanOverFlow

+0

Вы сказали, что оригинал без индексов занял 3-6 секунд. Насколько быстрее? (В любом случае, если миллионы записей совпадают, ничего нельзя сделать, кроме предварительного вычисления некоторых совокупных значений.) –

+0

~ 1,5-3 секунды. Это определенно намного быстрее, но все же недостаточно. Благодарю вас, я всегда ценю ваши ответы. Итак, мы пытаемся реализовать хорошее решение с предварительным вычислением результатов прямо сейчас. – StefanOverFlow

Смежные вопросы