Должно ли ВНУТРЕННЕЕ ВСТУПЛЕНИЕ в СОЮЗ с GROUP BY занять несколько часов в SQLite? - PullRequest
1 голос
/ 18 ноября 2010

Я пытаюсь изучить SQLite и ищу способы ускорить мой запрос.Я вижу здесь некоторых, пытающихся выжать мс, когда я легко за мега секунд.У меня есть одна база данных SQLite с четырьмя таблицами, хотя я запрашиваю только три таблицы.Вот запрос (я использую R для вызова запроса):

SELECT a.date, a.symbol, SUM (a.oi*a.contract_close) AS oi, c.ret, c.prc
    FROM (SELECT date, symbol, oi, contract_close FROM ann
            UNION
            SELECT date, symbol AS sym, oi, contract_close FROM qtr
            WHERE oi > 100 AND contract_close > 0 AND date > 20090600) a
    INNER JOIN
    (SELECT date, symbol || '1C' AS sym, ret, prc FROM crsp
            WHERE prc > 5 AND date>20090600) c
    ON a.date = c.date AND a.symbol = c.sym
    GROUP BY a.date, a.symbol

У меня есть индекс для каждой таблицы по дате и символу и просто VACUUMed, но он все еще очень медленный, как в течение часа плюс(и обратите внимание, что я ищу подмножество на шесть месяцев ... Я действительно хочу вернуться к 2003 году).

Это просто проблема размера кэша?У меня относительно новый ноутбук (MacBook Pro с 4 Гб оперативной памяти).Спасибо!

Вот это .schema:

CREATE TABLE ann 
( "date" INTEGER,
 symbol TEXT,
 contract_type_1 TEXT,
 contract_type_2 TEXT,
 product_type TEXT,
 block_volume INTEGER,
 oi_change INTEGER,
 oi INTEGER,
 efp_volume INTEGER,
 total_volume INTEGER,
 name TEXT,
 contract_change INTEGER,
 contract_open INTEGER,
 contract_high INTEGER,
 contract_low INTEGER,
 contract_close INTEGER,
 contract_settle INTEGER 
);
CREATE TABLE crsp 
( "date" INTEGER,
 symbol TEXT,
 permno INTEGER,
 prc REAL,
 ret REAL,
 vwretd REAL,
 ewretd REAL,
 sprtrn REAL 
);
CREATE TABLE dly 
( "date" INTEGER,
 symbol TEXT,
 expiration INTEGER,
 product_type TEXT,
 shares_per_contract INTEGER,
 "open" REAL,
 high REAL,
 low REAL,
 "last" REAL,
 settle REAL,
 change REAL,
 total_volume INTEGER,
 efp_volume INTEGER,
 block_volume INTEGER,
 oi INTEGER 
);
CREATE TABLE qtr 
( "date" INTEGER,
 symbol TEXT,
 total_volume INTEGER,
 block_volume INTEGER,
 efp_volume INTEGER,
 contract_high INTEGER,
 contract_low INTEGER,
 contract_open INTEGER,
 contract_close INTEGER,
 contract_settle INTEGER,
 oi INTEGER,
 oi_change INTEGER,
 shares_per_contract INTEGER,
 expiration INTEGER,
 product_type TEXT,
 unk TEXT,
 name TEXT 
);
CREATE INDEX idx_ann_date_sym ON ann (date, symbol);
CREATE INDEX idx_crsp_date_sym ON ann (date, symbol);
CREATE INDEX idx_dly_date_sym ON ann (date, symbol);
CREATE INDEX idx_qtr_date_sym ON ann (date, symbol);

Ответы [ 2 ]

3 голосов
/ 18 ноября 2010

Вы не упоминаете критически важную информацию: сколько строк в каждой таблице и сколько в вашем наборе результатов. Запрос не должен занимать час, если у вас нет действительно огромных наборов данных.

Тем не менее, несколько вещей, которые я заметил в вашем запросе:

  1. Я предполагаю, что вы знаете, что в вашем UNION предложение WHERE применяется только ко второй таблице, и вы включаете всю таблицу "ann"?

  2. UNION ALL обычно работает быстрее простого UNION, если только вам действительно не нужна дедупликация, предоставляемая простым UNION.

  3. Вам не нужно повторять фильтр для поля даты на обеих сторонах JOIN. Достаточно одной стороны, и вы можете достичь разных результатов по скорости в зависимости от того, с какой стороны JOIN вы устанавливаете фильтр. Используя его в обоих местах, вы можете обмануть оптимизатор запросов.

  4. Я не уверен, что «AS sym» делает во втором SELECT в UNION, потому что этот столбец будет иметь имя «symbol» в выходных данных (из первого SELECT в UNION), и вы полагаться на символ имени в вашем основном операторе SELECT.

  5. В вашем основном операторе SELECT у вас нет c.ret и c.prc в агрегатных функциях, но вы не включаете их в GROUP BY, поэтому мне не ясно, какое значение вы ожидаете смотрите в результатах, если c содержит несколько строк для набора GROUP BY.

  6. JOIN нельзя оптимизировать, поскольку вы вычисляете одно из значений JOIN как часть внутреннего SELECT. Я не уверен, есть ли умный способ переписать условия JOIN для оптимизации без сохранения рассчитанного значения символа в crsp.

  7. В зависимости от распределения значений символа и даты вы можете изменить порядок столбцов в своих индексах (но только если вы решите проблему вычисления значения символа).

1 голос
/ 18 ноября 2010

Как быстро это работает без ВНУТРЕННЕГО СОЕДИНЕНИЯ. Проверьте скорость обеих половин соединения.

Попробуйте

  • Выбор и сортировка по дате символа из C.
  • Внутреннее соединение с соединением A вместо таблицы C.
  • Удаление псевдонима символа как sym в половине объединения или псевдонима в обеих половинах.
...