Почему sqlite повторно сканирует таблицу с отчетливым значением? - PullRequest
0 голосов
/ 27 сентября 2018

Мне нужно получить различные элементы ref и alt.У меня есть очень эффективный запрос, пока я не добавлю отчет, и он отсканирует базовую таблицу?Так как у меня есть временная таблица, разве она не должна просто использовать это как источник данных?

   sqlite> explain query plan
       ...> select t1.ref, t1.alt from (SELECT * from Sample_szes where str_id 
        = 'STR_832206') as t1;


 selectid|order|from|detail
    1|0|0|SEARCH TABLE vcfBase AS base USING INDEX vcfBase_strid_idx ( . 
     str_id=?) (~10 rows)
     1|1|1|SEARCH TABLE vcfhomozyg AS hzyg USING INDEX homozyg_strid_idx 
     (str_id=?) (~10 rows)
      2|0|0|SEARCH TABLE vcfBase AS base USING INDEX vcfBase_strid_idx 
      (str_id=?) (~10 rows)
     2|1|1|SEARCH TABLE vcfAlt AS alt USING INDEX vcfAlt_strid_idx 
    (str_id=?) (~2 rows)
    2|2|2|SEARCH TABLE altGT AS gt USING INDEX altGT_strid_idx (str_id=?) (~2 rows)
    0|0|0|COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)

Добавить отличную и она повторно сканирует большую базовую таблицу.

sqlite> explain query plan
 ...> select distinct t1.ref, t1.alt from (SELECT * from Sample_szes 
 where str_id = 'STR_832206') as t1;

selectid|order|from|detail
2|0|0|SCAN TABLE vcfBase AS base (~1000000 rows)
2|1|1|SEARCH TABLE vcfhomozyg AS hzyg USING INDEX homozyg_strid_idx 
(str_id=?) (~10 rows)
3|0|0|SCAN TABLE vcfBase AS base (~1000000 rows)
3|1|1|SEARCH TABLE vcfAlt AS alt USING INDEX vcfAlt_strid_idx (str_id=?) (~2 rows)
3|2|2|SEARCH TABLE altGT AS gt USING INDEX altGT_strid_idx (str_id=?) (~2 rows)
1|0|0|COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)
0|0|0|SCAN SUBQUERY 1 (~1400000 rows)
0|0|0|USE TEMP B-TREE FOR DISTINCT

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Вы должны создать составной индекс для столбцов ref и alt .Индекс будет затем использоваться.В противном случае создается временный B-TREE (индекс), который требует полного сканирования для сортировки данных для индекса.

Я полагаю, что объяснение таково: -

Если запрос SELECT содержит предложение ORDER BY, GROUP BY или DISTINCT, SQLite может понадобиться использовать временную структуру b-деревасортировать выходные строки.Или это может использовать индекс.Использование индекса почти всегда намного эффективнее, чем выполнение сортировки.

Если требуется временное b-дерево, в выходной файл EXPLAIN QUERY PLAN добавляется запись с полем «detail», для которого установлено строковое значение в форме «USE TEMP B-TREE FOR xxx», гдеххх является одним из "ORDER BY", "GROUP BY" или "DISTINCT".Например:

sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c;
QUERY PLAN
|--SCAN TABLE t2
`--USE TEMP B-TREE FOR ORDER BY

В этом случае можно избежать использования временного b-дерева путем создания индекса для t2 (c) следующим образом:

sqlite> CREATE INDEX i4 ON t2(c);
sqlite> EXPLAIN QUERY PLAN SELECT c, d FROM t2 ORDER BY c; 
QUERY PLAN
`--SCAN TABLE t2 USING INDEX i4

ОБЪЯСНИТЬПЛАН ЗАПРОСА - 1.2.Временные сортировочные B-деревья

0 голосов
/ 27 сентября 2018

Я думаю, я мог бы найти ответ.на моем Mac у меня установлена ​​следующая версия sqlite

SQLite версия 3.19.3 2017-06-27 16: 48: 08

    sqlite> explain query plan
   ...> select distinct t1.ref, t1.alt from (SELECT * from Sample_szes where str_id = 'STR_832206') as t1;
2|0|1|SEARCH TABLE vcfhomozyg AS hzyg USING INDEX homozyg_strid_idx (str_id=?)
2|1|0|SEARCH TABLE vcfBase AS base USING INDEX vcfBase_strid_idx (str_id=?)
3|0|1|SEARCH TABLE vcfAlt AS alt USING INDEX vcfAlt_strid_idx (str_id=?)
3|1|0|SEARCH TABLE vcfBase AS base USING INDEX vcfBase_strid_idx (str_id=?)
3|2|2|SEARCH TABLE altGT AS gt USING INDEX altGT_strid_idx (str_id=?)
1|0|0|COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)
0|0|0|SCAN SUBQUERY 1
0|0|0|USE TEMP B-TREE FOR DISTINCT
...