首页 > 解决方案 > SQLite 在 WHERE 子句中使用 OR 条件花费了太多时间

问题描述

我有一个包含1 亿行的 SQLite 数据库(表) 。

表架构:

CREATE TABLE users
(
    u_id      VARCHAR(32) PRIMARY KEY,
    u_status  BOOLEAN,
    u_country VARCHAR(2),
    u_score   INT
);

CREATE INDEX dex_sta ON users (u_status);
CREATE INDEX dex_cou ON users (u_country);
CREATE INDEX dex_sco ON users (u_score);

CREATE INDEX dex_sns ON users (u_status, u_score);
CREATE INDEX dex_mul ON users (u_status, u_country, u_score);

当我在不选择多个国家/地区的情况下使用以下这些简单查询时,我在15 毫秒内得到了响应。

SELECT * FROM users WHERE u_status = 1 AND u_country = 'US' ORDER BY u_score DESC LIMIT 10 OFFSET 100000;

SELECT * FROM users WHERE u_status = 1 AND u_country = 'IN' ORDER BY u_score DESC LIMIT 10 OFFSET 100000;

问题从以下查询开始

当我尝试使用OR条件查询匹配多个国家/地区时,需要60 秒才能响应。

SELECT * FROM users WHERE u_status = 1 AND (u_country = 'US' OR u_country = 'IN') ORDER BY u_score DESC LIMIT 10 OFFSET 100000;

查询改进1:

当我通过( INDEXED BY )强制查询使用特定索引时,它会在1 秒内响应

SELECT * FROM users INDEXED BY dex_mul WHERE u_status = 1 AND (u_country = 'US' OR u_country = 'IN') ORDER BY u_score DESC LIMIT 10 OFFSET 100000;

查询改进2:

当我使用UNION ALL查询时,需要500 毫秒才能响应

SELECT * FROM users WHERE u_status = 1 AND u_country = 'US'
UNION ALL
SELECT * FROM users WHERE u_status = 1 AND u_country = 'IN'
ORDER BY u_score DESC LIMIT 10 OFFSET 100000;

是否有可能在< 50 毫秒内获得响应,例如匹配多个国家/地区的第一次查询?

标签: sqliteselectwhere-clause

解决方案


在查询中使用OR条件不允许使用索引。您可以将查询转换为UNION ALL子句 -

SELECT *
FROM users
WHERE u_status = 1 AND u_country = 'US'
UNION ALL
SELECT *
FROM users
WHERE u_status = 1 AND u_country = 'IN'
ORDER BY u_score DESC LIMIT 10 OFFSET 100000;

这可能会解决您的问题。


推荐阅读