2015-09-26 3 views
0

Я использую запрос sqlite для поиска двигателя с наилучшим набором калибровочных значений с использованием определенной формулы. В исходном запросе я заказываю вычисляемый столбец (для выбора top 1), это, по-моему, замедляет мой запрос.Оптимизировать запрос SQLite с упорядочением по вычисленному столбцу?

Я стараюсь сделать этот запрос как можно быстрее. В настоящее время время выполнения составляет около 0,300 секунды, и я смог уменьшить его до 0.150 секунд, ограничив таблицу Volume BETWEEN (0.9*1.7006359100341797) AND (1.1*1.7006359100341797) и используя tempTable для сортировки вычисленной таблицы (BestMotor).

Что еще я могу сделать, чтобы улучшить это? Стол имеет таблицу 30000 строк. Количество отдельных MotorVendors составляет около 55.

Вот мой оригинальный запрос: Я пытаюсь найти CalX и CalY, которые ближе всего к указанному тому для каждого отдельного MotorVendor.

SELECT T.MotorVendor, ((1/(CalX)+1/(CalY))) AS BestMotor FROM (
SELECT MotorVendor, 
     (SELECT CalX 
     FROM MotorTable AS T2 
     WHERE MotorType = 'text' and T2.MotorVendor = Tools.MotorVendor 
     ORDER BY abs(Volume - 1.7006359100341797) 
     LIMIT 1 
     ) AS CalX, 
     (SELECT CalY 
     FROM MotorTable AS T2 
     WHERE MotorType = 'text' and T2.MotorVendor = Tools.MotorVendor 
     ORDER BY abs(Volume - 1.7006359100341797) 
     LIMIT 1 
     ) AS CalY 
FROM (SELECT DISTINCT MotorVendor, 
     FROM MotorTable) AS Tools) AS T 
     WHERE T.CalX != '' AND T.CalY != '' 
     ORDER BY BestMotor DESC 
     LIMIT 1; 

А вот запрос с использованием TempTable заказать вычисляемый столбец (с индексом на этом вычисляемый столбец в TempTable):

DELETE FROM TempTable; 
INSERT INTO TempTable SELECT T.MotorVendor, ((1/(CalX)+1/(CalY))) AS BestMotor FROM (
SELECT MotorVendor, 
     (SELECT CalX 
     FROM MotorTable AS T2 
     WHERE MotorType = 'text' and T2.MotorVendor = Tools.MotorVendor AND Volume BETWEEN (0.9*1.7006359100341797) AND (1.1*1.7006359100341797) 
     ORDER BY abs(Volume - 1.7006359100341797) 
     LIMIT 1 
     ) AS CalX, 
     (SELECT CalX 
     FROM MotorTable AS T2 
     WHERE MotorType = 'text' and T2.MotorVendor = Tools.MotorVendor AND Volume BETWEEN (0.9*1.7006359100341797) AND (1.1*1.7006359100341797) 
     ORDER BY abs(Volume - 1.7006359100341797) 
     LIMIT 1 
     ) AS CalX 
FROM (SELECT DISTINCT MotorVendor, 
     FROM MotorTable) AS Tools) AS T 
     WHERE T.CalX != '' AND T.CalY != '' 
     ORDER BY BestMotor DESC 
     LIMIT 1; 
SELECT MotorVendor, BestMotor FROM TempTable ORDER BY BestMotor DESC LIMIT 1; 

UPDATE ...

я смог уменьшить его до 0.05 секунд ... Я создал таблицу для хранения всех отдельных MotorVendor и сменить основной запрос на это:

SELECT T.MotorVendor FROM (
SELECT MotorVendor, 
     (SELECT CalX 
     FROM MotorTable AS T2 
     WHERE MotorType = 'text' and T2.MotorVendor = Tools.MotorVendor AND Volume BETWEEN (0.9*1.7006359100341797) AND (1.1*1.7006359100341797) 
     ORDER BY abs(Volume - 1.7006359100341797) 
     LIMIT 1 
     ) AS CalX, 
     (SELECT CalY 
     FROM MotorTable AS T3 
     WHERE MotorType = 'text' and T3.MotorVendor = Tools.MotorVendor AND Volume BETWEEN (0.9*1.7006359100341797) AND (1.1*1.7006359100341797) 
     ORDER BY abs(Volume - 1.7006359100341797) 
     LIMIT 1 
     ) AS CalY  
FROM TempMotorVendorTable AS Tools) AS T 
     ORDER BY ((1/(CalX)+1/(CalY))) DESC LIMIT 1; 

Вот схемы двух таблиц и индексов, которые я создал.

CREATE TABLE MotorTable (
    CalY real, 
    CalX real, 
    Volume real, 
    MotorType text, 
    MotorVendor text 
); 
CREATE TABLE TempMotorVendorTable (
    MotorVendor TEXT 
); 
CREATE INDEX `MotorVendorIndex` ON MotorTable (`MotorVendor` ASC) 
CREATE INDEX VolumeIndex ON MotorTable (Volume DESC) 

Выход EXPLAIN QUERY ПЛАН

"0" "0" "0" "SCAN TABLE TempMotorVendorTable AS Tools" 
"0" "1" "1" "SEARCH TABLE MotorTable USING AUTOMATIC COVERING INDEX (MotorVendor=?)" 
"0" "0" "0" "EXECUTE CORRELATED SCALAR SUBQUERY 1" 
"1" "0" "0" "SEARCH TABLE MotorTable AS T2 USING INDEX CompToolIndex (MotorVendor=?)" 
"1" "0" "0" "USE TEMP B-TREE FOR ORDER BY" 
"0" "0" "0" "EXECUTE CORRELATED SCALAR SUBQUERY 2" 
"2" "0" "0" "SEARCH TABLE MotorTable AS T3 USING INDEX CompToolIndex (MotorVendor=?)" 
"2" "0" "0" "USE TEMP B-TREE FOR ORDER BY" 
"0" "0" "0" "USE TEMP B-TREE FOR ORDER BY" 
+0

Показать схему базы данных и вывод [EXPLAIN PLAN ЗАПРОСА] (http://www.sqlite.org/eqp.html). –

+0

Только что обновил мой вопрос более подробно для схемы и вывода 'EXPLAIN QUERY PLAN' – 22332112

+0

Что такое' historyCR'? –

ответ

1

ORDER BY abs(Volume - 1.234) не могут быть оптимизированы с индексом. (даже в следующей версии SQLite, которая будет иметь индексы выражений, так как значение 1.234 не является постоянной величиной.)

Однако, вы на самом деле не хотите, чтобы заказать все строки, вы просто хотите один ближайшая строка. Это можно сделать с помощью другого запроса, который ищет первую строку ниже, что значение и первая строка выше это значение (эти поисковые запросы и сортировки по Volume могут использовать индекс). Затем возьмите ближайший из этих двух строк (сортировка только два ряда быстро):

(SELECT CalX 
FROM (SELECT CalX, diff 
     FROM (-- get the largest value at or below 1.234 
      SELECT CalX, abs(Volume - 1.234) AS diff 
      FROM MotorTable AS T2 
      WHERE MotorType = 'text' 
       AND MotorVendor = Tools.MotorVendor 
       AND Volume <= 1.234 
      ORDER BY Volume DESC 
      LIMIT 1) 
     UNION ALL 
     SELECT CalX, diff 
     FROM (-- get the smallest value above 1.234 
      SELECT CalX, abs(Volume - 1.234) AS diff 
      FROM MotorTable AS T2 
      WHERE MotorType = 'text' 
       AND MotorVendor = Tools.MotorVendor 
       AND Volume > 1.234 
      ORDER BY Volume ASC 
      LIMIT 1) 
     ORDER BY diff 
     LIMIT 1) 
) 

Чтобы сделать поиск в MotorTable эффективным, вам нужен единый индекс на всех трех столбцах, и сравнение неравенство должно быть на последнем:

CREATE INDEX xxx ON MotorTable(MotorType, MotorVendor, Volume); 
+0

Просто добавив правильный индекс, он выполнил всего 0,004 секунды. Я также попытаюсь изменить запрос. Благодарю. – 22332112

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