使用较新版本的 System.Data.SQLite/sqlite3.dll 在 SQLite 数据库上使用子查询进行查询大约慢 10 倍

本文介绍了使用较新版本的 System.Data.SQLite/sqlite3.dll 在 SQLite 数据库上使用子查询进行查询大约慢 10 倍的处理方法,对大家解决问题具有一定的参考价值

问题描述

(见下方更新)

在从 C#.Net 应用程序(约 5 秒)中查询大约 500,000 行的非常简单的 Sqlite 数据表时,我遇到了查询性能缓慢的问题.

I am having an issue of slow query performance when querying a very simplistic Sqlite datatable of about 500,000 rows from within a C#.Net application (~5sec).

我使用 LinqPad 以及 2 个数据库浏览器(均基于 QtSql)在完全相同的数据库上尝试了完全相同的查询,它的运行速度提高了 10 倍(约 0.5 秒).相同的查询,相同的数据库,不同的应用程序,只有我的运行速度不快.

I have tried the exact same query on exactly the same database using LinqPad, as well as 2 database browsers (both based on QtSql), and it runs 10x faster (~0.5secs). Same query, same db, different apps, only mine doesn't run fast.

无论我是返回值还是仅返回一个 Count(*),它的区别可以忽略不计.

It makes negligible difference whether I'm returning values or just a Count(*).

我试过了:

  • 为每个 .Net 3.5/4/4.5 构建
  • 为 AnyCPU/x86/x64 中的每一个构建
  • 使用 System.Data.Sqlite、sqlite-net 中的每一个,以及通过 COM 直接访问 sqlite3 dll
  • 为每个 WPF/WinForms 构建
  • 查询的不同变体

这些都不会对查询时间产生任何明显的影响.

None of these make any noticible difference to the query time.

我知道使用 JOIN 重写查询可能会有所帮助,但我无法弄清楚为什么相同的查询在 LinqPad/Sql 浏览器中可以正常工作,但在我尝试创建的任何应用程序中都不能正常工作.我一定遗漏了一些非常基本的东西.

I know that rewriting the query using JOINs may help, but what I can't figure out is why the same query works fine in LinqPad/Sql browers but not from any app I try to create. I must be missing something pretty fundamental.

示例表:

"CREATE TABLE items(id INTEGER PRIMARY KEY, id1 INTEGER, id2 INTEGER, value INTEGER)"

示例查询字符串(尽管基本上任何使用子查询的查询都需要很长时间):

Example Query String (though basically any query using a subquery takes a long time):

SELECT count(*) 
FROM items WHERE 
id2 IN 
(
    SELECT DISTINCT id2 FROM items WHERE id1 IN 
    (
        SELECT DISTINCT id1 FROM items WHERE id2 = 100000 AND value = 10
    )
    AND value = 10
) 
AND value = 10 
GROUP BY id2

我知道这可能会使用 JOINS 和索引来重新编写以加快速度,但事实仍然是,此查询在其他应用程序中的运行速度要快得多.我在这里遗漏了什么,为什么无论我尝试什么,相同的查询都会运行得这么慢?

I know this could probably be re-written using JOINS and indexing to speed it up, but the fact remains that this query works significantly faster from other apps. What am I missing here as to why the same query runs so much slower no matter what I try?

更新: 似乎 sqlite 的版本与问题有关.使用旧的 System.Data.Sqlite v1.0.66.0 查询就像其他应用程序一样运行,但是使用更新的版本很慢.我还没有确定具体在哪个版本发生了变化,但我很确定这与底层的 sqlite3 版本有关,而不是专门针对 System.Data.Sqlite.如果有人知道在这种情况下可能发生了什么变化会导致子查询速度变慢,或者如果有设置或某些东西可以使新版本的 sqlite 中的子查询运行得更快,请告诉我!

UPDATE: It seems the version of sqlite has something to do with the issue. Using the legacy System.Data.Sqlite v1.0.66.0 the query runs just like the other apps, however using a more recent version it is slow. I haven't pinpointed what at what version exactly this changed, but am pretty sure it's to do with the underlying sqlite3 version not System.Data.Sqlite specifically. If anyone knows what could have changed that would cause subqueries to slow down so much in this situation, or if there are settings or something that can make subqueries run faster in new versions of sqlite please let me know!

同样,该查询是一个示例,并不理想且部分冗余......问题更多是关于为什么它在一个而不是另一个中起作用.

Again, the query is an example and is not ideal and partially redundant... the question is more about why it works in one and not the other.

提前感谢您提供任何额外的意见!

Thanks in advance for any additional input!

更新:已解决

请看下面我的回答.

推荐答案

好吧,原来这与 SQLite 1.7.0 引入的自动索引有关.在我的情况下,在这种没有索引的表上使用子查询意味着 SQLite 创建自动索引所花费的时间会导致查询遇到的额外开销.

Ok turns out it was to do with Automatic Indexing, which was introduced with SQLite 1.7.0. In my situation using subqueries on this kind of table without indexes meant that the time it took SQLite to create the automatic indexes was causing the additional overhead that the queries were experiencing.

解决方案是使用:

PRAGMA automatic_index=OFF;

在任何使用IN"子句的查询的开头.

at the start of any query that uses the "IN" clause.

在列上创建索引也可以解决这个问题(未经测试),但是在这种特殊情况下,创建索引所需的额外大小/磁盘使用是不值得的.

Creating indexes on the columns may also solve this (untested), however in this particular situation the additional size/disk usage necessary to create the indexes is not worth it.

这也表明我使用的 LinqPad SQLite 插件和数据库查看器基于旧的 sqlite 版本.

This would also suggest that the LinqPad SQLite plugin and the database viewers I was using are based on old sqlite versions.

更多信息请访问:

http://www.sqlite.org/src/info/8011086c85c6c4040

http://www.sqlite.org/optoverview.html#autoindex

感谢所有回复的人.

这篇关于使用较新版本的 System.Data.SQLite/sqlite3.dll 在 SQLite 数据库上使用子查询进行查询大约慢 10 倍的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2

admin_action_{$_REQUEST[‘action’]}

do_action( "admin_action_{$_REQUEST[‘action’]}" )动作钩子::在发送“Action”请求变量时激发。Action Hook: Fires when an ‘action’ request variable is sent.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$_REQUEST['action']引用从GET或POST请求派生的操作。源码(Source)更新版本源码位置使用被使用2.6.0 wp-admin/admin.php:...

日期:2020-09-02 17:44:16 浏览:1158

admin_footer-{$GLOBALS[‘hook_suffix’]}

do_action( "admin_footer-{$GLOBALS[‘hook_suffix’]}", string $hook_suffix )操作挂钩:在默认页脚脚本之后打印脚本或数据。Action Hook: Print scripts or data after the default footer scripts.目录锚点:#说明#参数#源码说明(Description)钩子名的动态部分,$GLOBALS['hook_suffix']引用当前页的全局钩子后缀。参数(Parameters)参数类...

日期:2020-09-02 17:44:20 浏览:1060

customize_save_{$this->id_data[‘base’]}

do_action( "customize_save_{$this->id_data[‘base’]}", WP_Customize_Setting $this )动作钩子::在调用WP_Customize_Setting::save()方法时激发。Action Hook: Fires when the WP_Customize_Setting::save() method is called.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_data...

日期:2020-08-15 15:47:24 浏览:798

customize_value_{$this->id_data[‘base’]}

apply_filters( "customize_value_{$this->id_data[‘base’]}", mixed $default )过滤器::过滤未作为主题模式或选项处理的自定义设置值。Filter Hook: Filter a Customize setting value not handled as a theme_mod or option.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_date['base'],指的是设置...

日期:2020-08-15 15:47:24 浏览:885

get_comment_author_url

过滤钩子:过滤评论作者的URL。Filter Hook: Filters the comment author’s URL.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/comment-template.php:32610...

日期:2020-08-10 23:06:14 浏览:925

network_admin_edit_{$_GET[‘action’]}

do_action( "network_admin_edit_{$_GET[‘action’]}" )操作挂钩:启动请求的处理程序操作。Action Hook: Fires the requested handler action.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$u GET['action']引用请求的操作的名称。源码(Source)更新版本源码位置使用被使用3.1.0 wp-admin/network/edit.php:3600...

日期:2020-08-02 09:56:09 浏览:870

network_sites_updated_message_{$_GET[‘updated’]}

apply_filters( "network_sites_updated_message_{$_GET[‘updated’]}", string $msg )筛选器挂钩:在网络管理中筛选特定的非默认站点更新消息。Filter Hook: Filters a specific, non-default site-updated message in the Network admin.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分$_GET['updated']引用了非默认的...

日期:2020-08-02 09:56:03 浏览:854

pre_wp_is_site_initialized

过滤器::过滤在访问数据库之前是否初始化站点的检查。Filter Hook: Filters the check for whether a site is initialized before the database is accessed.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/ms-site.php:93910...

日期:2020-07-29 10:15:38 浏览:825

WordPress 的SEO 教学:如何在网站中加入关键字(Meta Keywords)与Meta 描述(Meta Description)?

你想在WordPress 中添加关键字和meta 描述吗?关键字和meta 描述使你能够提高网站的SEO。在本文中,我们将向你展示如何在WordPress 中正确添加关键字和meta 描述。为什么要在WordPress 中添加关键字和Meta 描述?关键字和说明让搜寻引擎更了解您的帖子和页面的内容。关键词是人们寻找您发布的内容时,可能会搜索的重要词语或片语。而Meta Description则是对你的页面和文章的简要描述。如果你想要了解更多关于中继标签的资讯,可以参考Google的说明。Meta 关键字和描...

日期:2020-10-03 21:18:25 浏览:1688

谷歌的SEO是什么

SEO (Search Engine Optimization)中文是搜寻引擎最佳化,意思近于「关键字自然排序」、「网站排名优化」。简言之,SEO是以搜索引擎(如Google、Bing)为曝光媒体的行销手法。例如搜寻「wordpress教学」,会看到本站的「WordPress教学:12个课程…」排行Google第一:关键字:wordpress教学、wordpress课程…若搜寻「网站架设」,则会看到另一个网页排名第1:关键字:网站架设、架站…以上两个网页,每月从搜寻引擎导入自然流量,达2万4千:每月「有机搜...

日期:2020-10-30 17:23:57 浏览:1294