如果有不同的方法来完成相同的任务,如何选择最佳的SQL查询?

squ*_*rel 3 sql sqlite

我正在学习SQL(使用SQLite 3及其sqlite3命令行工具),我注意到我可以通过多种方式做一些事情,有时候不清楚哪一个更好.这里有三个查询该做同样的事情,一是通过执行intersect,另外通过inner joindistinct,最后一个类似于第二之一,但它包含过滤通过where.(第一个是由我正在阅读的书的作者和我自己写的其他人写的.)

问题是,哪些查询更好,为什么?而且,更一般地说,我怎么知道一个查询何时比另一个更好?是否有一些我错过的指南,或者我应该学习SQLite内部,尽管SQL的声明性质?

(在下面的例子中,有一些描述在一些电视剧中提到食品名称表.Foods_episodes是许多一对多连接表,而其他同季数描述食品名称和插曲的名字连在一起.请注意,所有时间的前十名正在寻找食物(基于所有系列中出现的数量),而不仅仅是季节中的顶级食物3 ... 5)

-- task
--     find the all-time top ten foods that appear in seasons 3 through 5
-- schema
--     CREATE TABLE episodes (
--       id integer primary key,
--       season int,
--       name text );
--     CREATE TABLE foods(
--       id integer primary key,
--       name text );
--     CREATE TABLE foods_episodes(
--       food_id integer,
--       episode_id integer );



select f.* from foods f 
inner join 
    (select food_id, count(food_id) as count 
        from foods_episodes 
        group by food_id 
        order by count(food_id) desc limit 10) top_foods 
    on f.id=top_foods.food_id 
intersect 
select f.* from foods f 
    inner join foods_episodes fe on f.id = fe.food_id 
    inner join episodes e on fe.episode_id = e.id 
where
    e.season between 3 and 5 
order by
    f.name; 



select
    distinct f.*
from
    foods_episodes as fe
    inner join episodes as e on e.id = fe.episode_id
    inner join foods as f on fe.food_id = f.id
    inner join (select food_id from foods_episodes
        group by food_id order by count(*) desc limit 10) as lol
        on lol.food_id = fe.food_id
where
    e.season between 3 and 5
order by 
    f.name;



select
    distinct f.*
from
    foods_episodes as fe
    inner join episodes as e on e.id = fe.episode_id
    inner join foods as f on fe.food_id = f.id
where
    fe.food_id in (select food_id from foods_episodes
        group by food_id order by count(*) desc limit 10)
    and e.season between 3 and 5
order by 
    f.name;

-- output (same for these thee):

-- id          name      
-- ----------  ----------
-- 4           Bear Claws
-- 146         Decaf Capp
-- 153         Hennigen's
-- 55          Kasha     
-- 94          Ketchup   
-- 164         Naya Water
-- 317         Pizza     
-- CPU Time: user 0.000000 sys 0.000000
Run Code Online (Sandbox Code Playgroud)

Gir*_*Rao 6

与MySQL类似,看起来SQLlite有一个EXPLAIN命令.使用EXPLAIN关键字前置您的选择,它将返回有关查询的信息,包括扫描的行数和使用的索引.

http://www.sqlite.org/lang_explain.html

通过在各种选择上运行EXPLAIN,您可以确定哪些查询(和子查询)比其他查询更有效.

以下是SQLlite的查询规划器和优化的一般概述:http://sqlite.org/optoverview.html

SQLlite3还支持回调函数来跟踪查询.您必须实现它:http://www.sqlite.org/c3ref/profile.html