2012-05-07 5 views
2

У меня есть простая таблица (около 8 столбцов и много строк) в базе данных SQLite. Существует одна программа, которая работает как служба и часто выполняет выбор, обновление и вставки на столе (примерно каждые 5 минут). Выборы используются только для определения того, какие строки должны быть обновлены, и они основаны на столбце, который содержит логические значения (вероятно, переводится в integer внутри SQLite).Sqlite view vs plain statement statement performance

Существует также веб-приложение, которое выполняет выбор (всегда с предложением GROUP BY) всякий раз, когда веб-пользователь хочет просмотреть часть данных.

Существует два способа запроса данных через веб-приложение: (a) предопределенные фильтры (то есть предложение where имеет особые условия для 3 конкретных столбцов) и (b) пользовательские фильтры (то есть пользователь выбирает значения для но столбцы, участвующие в условии where, такие же, как в (a)). Как уже упоминалось, в обоих случаях выполняется операция GROUP BY.

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

РЕДАКТИРОВАТЬ: Использование EXPLAIN план запроса на "предопределенные" SELECT урожайности заявление только одну строку:

0|0|TABLE mytable 

Использование EXPLAIN на том же запросе, приводит к следующему:

0|OpenVirtual|1|4|keyinfo(2,-BINARY,BINARY) 
1|OpenVirtual|2|3|keyinfo(1,BINARY) 
2|MemInt|0|5| 
3|MemInt|0|4| 
4|Goto|0|27| 
5|MemInt|1|5| 
6|Return|0|0| 
7|IfMemPos|4|9| 
8|Return|0|0| 
9|AggFinal|0|0|count(0) 
10|AggFinal|2|1|sum(1) 
11|MemLoad|0|0| 
12|MemLoad|1|0| 
13|MemLoad|2|0| 
14|MakeRecord|3|0| 
15|MemLoad|0|0| 
16|MemLoad|1|0| 
17|Sequence|1|0| 
18|Pull|3|0| 
19|MakeRecord|4|0| 
20|IdxInsert|1|0| 
21|Return|0|0| 
22|MemNull|1|0| 
23|MemNull|3|0| 
24|MemNull|0|0| 
25|MemNull|2|0| 
26|Return|0|0| 
27|Gosub|0|22| 
28|Goto|0|82| 
29|Integer|0|0| 
30|OpenRead|0|2| 
31|SetNumColumns|0|9| 
32|Rewind|0|48| 
33|Column|0|8| 
34|String8|0|0|123456789 
35|Le|356|39|collseq(BINARY) 
36|Column|0|3| 
37|Integer|180|0| 
38|Gt|100|42|collseq(BINARY) 
39|Column|0|7| 
40|Integer|1|0| 
41|Ne|356|47|collseq(BINARY) 
42|Column|0|6| 
43|Sequence|2|0| 
44|Column|0|3| 
45|MakeRecord|3|0| 
46|IdxInsert|2|0| 
47|Next|0|33| 
48|Close|0|0| 
49|Sort|2|69| 
50|Column|2|0| 
51|MemStore|7|0| 
52|MemLoad|6|0| 
53|Eq|512|58|collseq(BINARY) 
54|MemMove|6|7| 
55|Gosub|0|7| 
56|IfMemPos|5|69| 
57|Gosub|0|22| 
58|AggStep|0|0|count(0) 
59|Column|2|2| 
60|Integer|30|0| 
61|Add|0|0| 
62|ToReal|0|0| 
63|AggStep|2|1|sum(1) 
64|Column|2|0| 
65|MemStore|1|1| 
66|MemInt|1|4| 
67|Next|2|50| 
68|Gosub|0|7| 
69|OpenPseudo|3|0| 
70|SetNumColumns|3|3| 
71|Sort|1|80| 
72|Integer|1|0| 
73|Column|1|3| 
74|Insert|3|0| 
75|Column|3|0| 
76|Column|3|1| 
77|Column|3|2| 
78|Callback|3|0| 
79|Next|1|72| 
80|Close|3|0| 
81|Halt|0|0| 
82|Transaction|0|0| 
83|VerifyCookie|0|1| 
84|Goto|0|29| 
85|Noop|0|0| 

ВЫБРАТЬ Я использовал следующее:

SELECT 
    COUNT(*) as number, 
    field1, 
    SUM(CAST(filter2 +30 AS float)) as column2 
FROM 
    mytable 
WHERE 
    (filter1 > '123456789' AND filter2 > 180) 
    OR filter3=1 
GROUP BY 
    field1 
ORDER BY 
    number DESC, field1; 
+0

Что скажет вам план запроса? –

+0

Я чувствую себя немного новичком здесь. План запроса? Я попробовал команду «объяснить запрос плана» в файле, и я получил только одну строку: «0 | 0 | TABLE mytable». Я также попробовал команду объяснения, которая дала достаточно выход, но я ничего не могу понять. Я обновляю вопрос, поскольку вывод объяснения слишком велик, чтобы перечислить здесь. – Yiangos

+0

[Документация: прочитайте. Любить это. Используйте его.] (Http://www.sqlite.org/lang_explain.html) –

ответ

1

Всякий раз, когда вы собираетесь b e делая сравнения поля непервичного ключа, хорошая идея дизайна для add an index в поле (и). Слишком много, однако, может вызвать INSERT s для сканирования, поэтому планируйте соответственно.

Кроме того, если у вас есть простые поля, такие как те, которые содержат только логическое значение, вам может потребоваться объявить его как INTEGER вместо того, что вы его объявили. Объявление его как любого типа, специально не определенного SQLite, будет cause it to default to a NUMERIC type, что займет больше времени для сравнения значений, поскольку оно будет хранить его внутренне как double и будет использовать математический процессор с плавающей запятой вместо целочисленного математического процессора.

IMO, GROUP BY Директива сортировки иногда является мертвой поддачей неоптимизированного запроса; его методология включает в себя устранение избыточных данных, которые можно было бы устранить заранее, если бы они не были извлечены из базы данных для начала.

EDIT:

Я видел ваш запрос и увидел, есть несколько простых вещей, которые вы можете сделать, чтобы оптимизировать его:

  • SUM(CAST(filter2 +30 AS float)) является неэффективным; почему вы бросаете его как поплавок? Почему бы не просто SUM затем добавить 30 * COUNT?

  • filter1 > '123456789' - Почему сравнение строк? Почему бы просто не использовать целочисленное сравнение?

+0

Я проверю схему таблиц и вернусь к вам по логической цепочки-числовой проблеме. Что касается группы, я использую ее для консолидации данных и сообщает количество записей с одинаковыми значениями (я не изменил фактическое количество полей, запрошенных запросом, только их имена). – Yiangos

+0

К сожалению, я не могу отредактировать свой комментарий выше. Булевский флаг действительно хранится в столбце аффинности INTEGER. – Yiangos

+0

Нет, это 'NUMERIC'. См. Таблицу [здесь] (http://www.sqlite.org/datatype3.html#affinity). – amphetamachine