AnA*_*ice 5 postgresql ruby-on-rails ruby-on-rails-3 postgresql-performance
我目前有以下内容:
User (id, fname, lname, deleted_at, guest)
Run Code Online (Sandbox Code Playgroud)
我可以通过它们的fname初始查询用户列表,如下所示:
User Load (9.6ms) SELECT "users".* FROM "users" WHERE (users.deleted_at IS NULL) AND (lower(left(fname, 1)) = 's') ORDER BY fname ASC LIMIT 25 OFFSET 0
Run Code Online (Sandbox Code Playgroud)
由于以下索引,这很快:
CREATE INDEX users_multi_idx
ON users (lower(left(fname, 1)), fname)
WHERE deleted_at IS NULL;
Run Code Online (Sandbox Code Playgroud)
我现在想要做的是能够查询所有不以字母AZ开头的用户.我这样做是这样的:
SELECT "users".* FROM "users" WHERE (users.deleted_at IS NULL) AND (lower(left(fname, 1)) ~ E'^[^a-zA-Z].*') ORDER BY fname ASC LIMIT 25 OFFSET 0
Run Code Online (Sandbox Code Playgroud)
但问题是这个查询非常慢并且似乎没有使用索引来加速第一个查询.关于如何优雅地使第二个查询(非az)更快的任何建议?
我正在使用带有rails 3.2的Postgres 9.1
谢谢
此处更新了之前问题的答案
。
我的第一个想法(索引text_pattern_ops)在我的测试中不适用于正则表达式。最好将您的查询重写为:
SELECT *
FROM users
WHERE deleted_at IS NULL
WHERE lower(left(fname, 1)) < 'a' COLLATE "C"
OR lower(left(fname, 1)) > 'z' COLLATE "C"
ORDER BY fname
LIMIT 25 OFFSET 0;Run Code Online (Sandbox Code Playgroud)
除了这些表达式通常更快之外,您的正则表达式中还包含大写字母,这与lower(). 与单个字符相比,尾随字符毫无意义。
并使用这个索引:
CREATE INDEX users_multi_idx
ON users (lower(left(fname, 1)) COLLATE "C", fname)
WHERE deleted_at IS NULL;Run Code Online (Sandbox Code Playgroud)
该COLLATE "C"部分是可选的,并且仅对性能产生非常小的影响。其目的是将排序规则重置为默认的 posix 排序规则,该排序规则仅使用字节顺序并且通常速度更快。当排序规则无论如何都不相关时很有用。
如果您使用它创建索引,则只有与排序规则匹配的查询才能使用它。因此,如果性能不是您的首要要求,您可能会跳过它以简化事情。
| 归档时间: |
|
| 查看次数: |
225 次 |
| 最近记录: |