sql—为什么带有“in”和“on”语句的查询会无限运行

goucqfw6  于 2021-08-01  发布在  Java
关注(0)|答案(1)|浏览(378)

我有三个表,表3基本上是表1和表2的中间表。当我执行包含“in”并连接table1和table3的查询语句时,它一直在运行,我无法得到结果。如果我使用 id=134 而不是 id in (134,267,390,4234 ... ) ,结果出来了。我不明白为什么“in”有效果,有人有想法吗?
查询语句:

  1. select count(*) from table1, table3 on id=table3.table1_id where table3.table2_id = 123 and id in (134,267,390,4234) and item = 30;

表结构:

  1. table1:
  2. id integer primary key,
  3. item integer
  4. table2:
  5. id integer,
  6. item integer
  7. table3:
  8. table1_id integer,
  9. table2_id integer
  10. -- the DB without index was 0.8 TB after the three indices is now 2.5 TB
  11. indices on: table1.item, table3.table1_id, table3.table2_id

环境:linux,sqlite 3.7.17

5sxhfpxr

5sxhfpxr1#

from table1, table3 在大多数数据库中是交叉连接,由于数据的大小,交叉连接是巨大的,但在sqlite3中它是一个内部连接。从sqlite中选择docs
旁注:交叉连接的特殊处理。“内部联接”、“联接”和“联接”运算符之间没有区别。它们在sqlite中完全可以互换。
在这种情况下,这不是你的问题,但我们不要试探命运;总是显式地写出连接。

  1. select count(*)
  2. from table1
  3. join table3 on id=table3.table1_id
  4. where table3.table2_id = 123
  5. and id in (134,267,390,4234);

因为您只是在计数,所以不需要表1中的任何数据,但是id.table3有table1\u id,所以不需要与table1联接。我们完全可以用table3连接表来实现这一点。

  1. select count(*)
  2. from table3
  3. where table2_id = 123
  4. and table1_id in (134,267,390,4234);

sqlite只能对每个表使用一个索引。要在如此大的数据集上执行此操作,需要两列的复合索引: table3(table1_id, table2_id) . 想必您不想要重复的,所以应该采用唯一索引的形式。这将包括对table1\u id的查询以及对table1\u id和table2\u id的查询;您应该删除table1\u id索引以节省空间和时间。

  1. create unique index table3_unique on table3(table1_id, table2_id);

对于只使用table2\u id的查询,复合索引不会保留现有的table2\u id索引。
您的查询现在应该运行lickity split。
有关更多信息,请阅读sqlite查询优化器。
太字节就是大量的数据。虽然sqlite在技术上可以处理这个问题,但它可能不是最好的选择。对于小型和简单的数据库来说,它是很好的,但是它缺少很多特性。您应该研究一个更强大的数据库,比如postgresql。它不是一个灵丹妙药,所有相同的原则都适用,但它更适合于这种规模的数据。

展开查看全部

相关问题