我正在构建一个相对较大的 SQLite 数据库。该数据库的一般访问配置文件是:
数据结构是一个扁平的非规范化表,查询的形式如下:
WHERE chromosome=TEXT, position=INT, reference_sequence=TEXT, alternate_sequence=TEXT
Run Code Online (Sandbox Code Playgroud)
我想根据数据库的内容验证传入查询是否请求有效的染色体名称。请求chromosome='chr13' 是有效的,但在'13' 或'chr31' 的情况下,我希望我的python 脚本抛出错误,而不是默默地返回零行。为了实现这一点,我在 python 类的初始化过程中,它进行了一个初始查询以获取一组有效的染色体名称:
SELECT DISTINCT chromosome from dbsnp;
Run Code Online (Sandbox Code Playgroud)
此查询需要很长时间,并且会导致执行停滞。我已经尝试了(染色体、位置、reference_sequence、alternate_sequence)上的复合索引以及染色体上的单个索引,并已通过 EXPLAIN QUERY PLAN 验证在这两种情况下都使用了索引。
sqlite> EXPLAIN QUERY PLAN SELECT DISTINCT chromosome FROM dbsnp;
order|from|detail
0|0|TABLE dbsnp WITH INDEX chromosome ORDER BY
Run Code Online (Sandbox Code Playgroud)
我的问题:是否有一些 SQL 技巧可以直接从染色体索引中查询。我不在乎行中的任何其他内容,而且索引似乎是我想要返回的数据的预构建版本。
或者,我正在考虑构建一个chromosome_names 表,在数据库加载和更新后用上面的SELECT DISTINCT 查询填充该表。因为它让我害怕构建一个可能与主表不同步的静态表,所以我正在考虑在主表更改时更新染色体名称表的触发器。但是,我担心如果我更新主表中的行,这可能会导致大量流失,更重要的是,我正在重新发明索引中基本包含的内容。
有没有一种好方法可以直接从索引中获取我的不同值查询,或者,如果查询的染色体值超出了包含的值集(注意:位置、参考、并且 alt 序列有时会查询意外的值,因此在返回的零行上出错将不起作用)。
谢谢
我从未使用过 SQLite,所以请耐心等待。但这个问题似乎在许多 RDBMS 平台中都很常见。
当您从列中选择不同的值时,您最终会扫描索引中的所有行:
如果表中没有很多行或者列没有很多重复值,这可能是一个很好的策略。但是,如果每个不同值都有数百万行,那么您将扫描数百万行只是为了返回一个唯一值。对于这样的数据集,有时最好获取第一个不同的值,然后跳到下一个值,依此类推。在某些平台中,这可以通过递归来完成。您还可以一次运行一个查询,每个查询都会获取下一个不同的值。例如,您可以使用以下查询获取第一个值:
SELECT MIN(chromosome) FROM dbsnp;
Run Code Online (Sandbox Code Playgroud)
然后使用此查询获取下一个值(用第一个查询的值替换过滤器):
SELECT chromosome FROM dbsnp WHERE chromosome > 'TEST_1' ORDER BY chromosome LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
下一个:
SELECT chromosome FROM dbsnp WHERE chromosome > 'TEST_2' ORDER BY chromosome LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
等等。对于这些查询,我得到索引搜索:
对于相对较小的数据集,单个不同查询大约需要 320 毫秒,而一系列LIMIT 1查询只需要 4 毫秒。当然,您需要编写更多代码才能使用此解决方案,但可能值得一试。
| 归档时间: |
|
| 查看次数: |
1679 次 |
| 最近记录: |