提高sqlite中SQL选择和连接的效率

提高sqlite中SQL选择和连接的效率,sql,database,sqlite,Sql,Database,Sqlite,我正在做一个个人项目,重点是分析数据库中的文本。我的目的是做一些有趣的事情,学习SQL和sqlite。因此,考虑到我的新手能力,我想得到关于如何更有效地完成这项工作的建议 比如说,我想在一篇文章A中挑出食物的种类。我分析我的文章,如果我发现一种食物F,那么我将F添加到表项目中。然后我将A.id和F.id添加到结果中。当我分析我的文章并找到一种食品G,它已经存在于项目中,我所做的就是将a.id和G.id添加到结果中 因此,我的模式如下所示: 文章:id,文章 结果:id、项目id、文章id 项目

我正在做一个个人项目,重点是分析数据库中的文本。我的目的是做一些有趣的事情,学习SQL和sqlite。因此,考虑到我的新手能力,我想得到关于如何更有效地完成这项工作的建议

比如说,我想在一篇文章
A
中挑出食物的种类。我分析我的文章,如果我发现一种食物
F
,那么我将
F
添加到表项目中。然后我将
A.id
F.id
添加到结果中。当我分析我的文章并找到一种食品
G
,它已经存在于项目中,我所做的就是将
a.id
G.id
添加到结果中

因此,我的模式如下所示:

  • 文章:
    id,文章
  • 结果:
    id、项目id、文章id
  • 项目:
    id、食物类型、食物
如果我想找到所有关于
橙子
葡萄
以及任何
蔬菜
的文章,那么我会从以下内容开始:

SELECT * 
  FROM articles 
INNER JOIN results ON articles.id = results.article_id  
INNER JOIN items ON results.item_id = items.id
并加上:

WHERE foodtype='vegetable' OR food='orange' OR food='grape'
实际上,我的数据库要大得多。有数千篇文章和超过十万个提取的“食物”。我加入3个表的大多数查询都不会返回,即使我将结果限制在100个。我尝试在我的
WHERE
子句中常见的字段上创建索引,如
food
foodtype
,但没有看到任何改进


我可以对我的数据库或查询进行改进吗?

首先,选择*是邪恶的。无论构建多少索引,查询都不会被覆盖(除非对整个表进行索引,从而使索引扫描和表扫描的成本相同)。 1.因此,选择要显示的列。 2.在id列上添加客户索引 3.在WHERE子句中的列上添加非聚集 4.在select查询中的列上放置覆盖索引


优化查询的最佳方法是查看执行计划和瓶颈步骤,但由于您的问题中没有瓶颈步骤,因此这是我可以做出的最佳猜测。首先,选择*是邪恶的。无论构建多少索引,查询都不会被覆盖(除非对整个表进行索引,从而使索引扫描和表扫描的成本相同)。 1.因此,选择要显示的列。 2.在id列上添加客户索引 3.在WHERE子句中的列上添加非聚集 4.在select查询中的列上放置覆盖索引


优化查询的最佳方法是查看执行计划和瓶颈步骤,但由于您的问题中没有瓶颈步骤,因此这是我可以做的最佳猜测,始终首先内部连接最小的表。我怀疑你不会有那么多的物品(也许?)。所以它应该是“小的内部连接大的内部连接最大的”。

始终先内部连接最小的表。我怀疑你不会有那么多的物品(也许?)。所以它应该是“小的内部连接大的内部连接最大的”。

只检索您需要的列 查询的第一个问题是
SELECT*
返回了查询中所有联接表中的所有列。这意味着将返回计算两侧的联接条件中的值。最好写出您需要的实际列,因为您列出的三个列都有一个
id
列——这会使正确的值检索变得复杂,除非使用序号位置(这不是一个好的做法——更改位置,数据检索不是应该的)

使用表别名可以最小化引用特定表所需的内容:

SELECT a.article 
  FROM ARTICLES a
  JOIN RESULTS r ON r.article_id = a.id
  JOIN ITEMS i ON i.id = r.item_id
索引 索引外键(用于连接条件的内容)应该是列表中仅次于表主键的第二件事

然后您必须定期运行,因为统计数据是

…不会随着数据库内容的更改而自动更新。如果数据库的内容发生显著变化,或者如果数据库模式发生变化,则应考虑重新分析分析命令以更新统计。 这些统计信息是优化器用于其查询决策的信息,以及索引的存在

ORs对性能的影响是出了名的 您可以尝试重新编写查询,使其不使用ORs和UNION:

SELECT a.article 
  FROM ARTICLES a
  JOIN RESULTS r ON r.article_id = a.id
  JOIN ITEMS i ON i.id = r.item_id
 WHERE i.foodtype = 'vegetable'
UNION 
SELECT a.article 
  FROM ARTICLES a
  JOIN RESULTS r ON r.article_id = a.id
  JOIN ITEMS i ON i.id = r.item_id
 WHERE i.food IN ('orange', 'grape')
请注意,
UNION
UNION ALL
慢,因为
UNION
删除重复项
UNION ALL
速度更快,因为它不会删除重复项。

只检索所需的列 查询的第一个问题是
SELECT*
返回了查询中所有联接表中的所有列。这意味着将返回计算两侧的联接条件中的值。最好写出您需要的实际列,因为您列出的三个列都有一个
id
列——这会使正确的值检索变得复杂,除非使用序号位置(这不是一个好的做法——更改位置,数据检索不是应该的)

使用表别名可以最小化引用特定表所需的内容:

SELECT a.article 
  FROM ARTICLES a
  JOIN RESULTS r ON r.article_id = a.id
  JOIN ITEMS i ON i.id = r.item_id
索引 索引外键(用于连接条件的内容)应该是列表中仅次于表主键的第二件事

然后您必须定期运行,因为统计数据是

…不会随着数据库内容的更改而自动更新。如果数据库的内容发生显著变化,或者如果数据库模式发生变化,则应考虑重新分析分析命令以更新统计。 这些统计信息是优化器用于其查询决策的信息,以及索引的存在

 select title, foodesc, foodtypedesc
 from articlefood AF
 join article A on AF.articleid=A.articleid
 join FOOD F on AF.foodid = F.foodid and fooddesc
 join FOODTYPE FT on FT.foodtypeid = F.foodtypeid 
 where .....
 select articleid from  ARTICLEFOOD 
 JOIN
 (
    select foodid from FOOD where  .... 
 ) as MyFoods
 ON ARTICLEFOOD.foodid = MyFoods.foodid

 UNION

 select articleid from  ARTICLEFOOD 
 JOIN
 (
    select foodtypeid from FOODTYPE where  .... 
 ) as MyFoodTypes
 ON ARTICLEFOOD.foodtypeid = MyFoodTypes.foodtypeid