我曾经有过如下查询:
MyModel.where(id: ids)
Run Code Online (Sandbox Code Playgroud)
哪个生成sql查询如:
SELECT "my_models".* FROM "my_models"
WHERE "my_models"."id" IN (1, 28, 7, 8, 12)
Run Code Online (Sandbox Code Playgroud)
现在我想改为使用ANY而不是IN.我创造了这个:
MyModel.where("id = ANY(VALUES(#{ids.join '),('}))"
Run Code Online (Sandbox Code Playgroud)
现在,当我使用空数组时,ids = []我得到以下错误:
MyModel Load (53.0ms) SELECT "my_models".* FROM "my_models" WHERE (id = ANY(VALUES()))
ActiveRecord::JDBCError: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
ActiveRecord::StatementInvalid: ActiveRecord::JDBCError: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
Position: 75: SELECT "social_messages".* FROM "social_messages" WHERE (id = ANY(VALUES()))
from arjdbc/jdbc/RubyJdbcConnection.java:838:in `execute_query'
Run Code Online (Sandbox Code Playgroud) 有没有办法优化这样的查询:
SELECT count(*) FROM mytable
WHERE
indexed_field IN ('v1', 'v2', ..., 'v2000')
AND NOT regular_field='something'
AND other_regular_field='something_else';
Run Code Online (Sandbox Code Playgroud)
这个查询“有效”。问题是它非常慢(1分钟以上)。我认为使用IN定义的列表来使用表达式就可以了,但事实证明并不是那么好。
我正在使用 Postgresql 9.6。
我的表有310K。
查询解释:
QUERY PLAN
Aggregate (cost=396158.70..396158.71 rows=1 width=8) (actual time=8630.558..8630.559 rows=1 loops=1)
-> Seq Scan on mytable (cost=0.00..396156.77 rows=772 width=0) (actual time=7853.840..8630.478 rows=916 loops=1)
Filter: (((non_indexed_field)::text <> 'value1'::text) AND ((non_indexed_field)::text = 'value2'::text) AND ((indexed_field)::text = ANY ('{lots and lots of values....}'::text[])))
Rows Removed by Filter: 306768
Planning time: 2.543 ms
Execution time: 8630.770 ms
Run Code Online (Sandbox Code Playgroud)
通过分析、缓冲:
Aggregate (cost=396158.70..396158.71 …Run Code Online (Sandbox Code Playgroud)