提高SQL的效率选择和加入sqlite

ty.*_*ty. 1 sql database sqlite

我正在开展一个专注于分析数据库中文本的个人项目.我的目的是做一些有趣的事情并了解SQL和sqlite.因此,考虑到我的新手能力,我希望得到更有效的建议.

比方说,我想在文章中挑选出各种食物A.我分析我的文章,如果我找到了食物F,那么我添加F到表.然后,添加A.idF.id结果.当我分析我的文章,并找到食物G中已经存在的项目,我要做的就是增加A.idG.id结果.

所以我的模式如下所示:

  • 文章: id, article
  • 结果: id, item_id, article_id
  • 项目: id, foodtype, food

如果我想找到所有谈论的文章orangesgrapes任何vegetable,然后我会像这样的东西开始:

SELECT * 
  FROM articles 
INNER JOIN results ON articles.id = results.article_id  
INNER JOIN items ON results.item_id = items.id
Run Code Online (Sandbox Code Playgroud)

并添加:

WHERE foodtype='vegetable' OR food='orange' OR food='grape'
Run Code Online (Sandbox Code Playgroud)

实际上,我的数据库要大得多.有成千上万的文章和超过十万个提取的"食物".即使我将事物限制为100个结果,我加入3个表的大多数查询也不会返回.我已经尝试在我的WHERE子句中常见的字段上创建一个索引,比如foodfoodtype,但是没有看到任何改进.

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

OMG*_*ies 6

仅检索您需要的列

查询的第一个问题SELECT *是返回查询中连接的所有表的所有列.这意味着返回评估两侧的JOIN标准中的值.最好写出你需要的实际列,因为你列出的所有三列都有一列 - 这使得正确的值检索变得复杂,除非使用顺序位置(不是一个好的做法 - 改变位置,数据检索不应该是它应该是什么) .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
Run Code Online (Sandbox Code Playgroud)

索引

索引外键 - 用于JOIN条件的内容,应该是表的主键后列表中的第二个内容.

然后你必须定期运行ANALYZE命令,因为统计数据是......

...随着数据库内容的变化而不会自动更新.如果数据库的内容发生显着变化,或者数据库模式发生更改,则应考虑重新运行ANALYZE命令以更新统计信息.

这些统计信息是优化程序用于查询决策以及索引存在的统计信息.

OR因性能而臭名昭着

您可以尝试重写该查询,以便它不使用带有UNION的OR:

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')
Run Code Online (Sandbox Code Playgroud)

请注意,这UNION比较慢UNION ALL,因为UNION删除了重复项. UNION ALL更快,因为它不会删除重复项.