Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择带索引的列或使用带索引的列非常慢_Sql_Performance_Composite Primary Key_Database Indexes_Cockroachdb - Fatal编程技术网

Sql 选择带索引的列或使用带索引的列非常慢

Sql 选择带索引的列或使用带索引的列非常慢,sql,performance,composite-primary-key,database-indexes,cockroachdb,Sql,Performance,Composite Primary Key,Database Indexes,Cockroachdb,我的蟑螂数据库中有一个具有以下定义的表: CREATE TABLE foo_value ( foo_id_a INT NOT NULL, foo_id_b INT NOT NULL, value FLOAT NULL, create_date_time TIMESTAMP NULL, update_date_time TIMESTAMP NULL, CONSTRAINT "primary" PRIMARY KEY (foo_id_a ASC, fo

我的蟑螂数据库中有一个具有以下定义的表:

CREATE TABLE foo_value (
    foo_id_a INT NOT NULL,
    foo_id_b INT NOT NULL,
    value FLOAT NULL,
    create_date_time TIMESTAMP NULL,
    update_date_time TIMESTAMP NULL,
    CONSTRAINT "primary" PRIMARY KEY (foo_id_a ASC, foo_id_b ASC),
    INDEX foo_value_foo_id_a_foo_id_b_idx (foo_id_a ASC, foo_id_b ASC),
    INDEX foo_id_a_idx (foo_id_a ASC),
    INDEX foo_id_b_idx (foo_id_b ASC),
    FAMILY "primary" (foo_id_a, foo_id_b, value, create_date_time, update_date_time)
)
它包含大约400000行

查询两个ID中的一个很快:

SELECT * FROM foo_db.foo_value WHERE foo_id_a = 123456;
takes 0.071 s

SELECT * FROM foo_db.foo_value WHERE foo_id_b = 123456;
takes 0.086 s
但是,查询其中一个的速度非常慢:

SELECT * FROM foo_db.foo_value WHERE foo_id_a = 123456 OR foo_id_b = 123456;
takes 2.739 s
为什么会这样

解释的结果如下所示:

EXPLAIN SELECT * FROM foo_db.foo_value WHERE foo_id_a = 321210483;
+-------+------+-------+-----------------------+
| Level | Type | Field |      Description      |
+-------+------+-------+-----------------------+
|     0 | scan |       |                       |
|     0 |      | table | foo_value@primary     |
|     0 |      | spans | /321210483-/321210484 |
+-------+------+-------+-----------------------+


EXPLAIN SELECT * FROM foo_db.foo_value WHERE foo_id_b = 321210483;
+-------+------------+-------+------------------------+
| Level |    Type    | Field |      Description       |
+-------+------------+-------+------------------------+
|     0 | index-join |       |                        |
|     1 | scan       |       |                        |
|     1 |            | table | foo_value@foo_id_b_idx |
|     1 |            | spans | /321210483-/321210484  |
|     1 | scan       |       |                        |
|     1 |            | table | foo_value@primary      |
+-------+------------+-------+------------------------+


EXPLAIN SELECT * FROM foo_db.foo_value WHERE foo_id_a = 321210483 OR foo_id_b = 321210483;
+-------+------+-------+-------------------+
| Level | Type | Field |    Description    |
+-------+------+-------+-------------------+
|     0 | scan |       |                   |
|     0 |      | table | foo_value@primary |
|     0 |      | spans | ALL               |
+-------+------+-------+-------------------+

您需要的是索引优化,它在or中使用两个不同的索引。遗憾的是,SQL引擎通常不支持这种优化,尽管Oracle和其他一些数据库一样支持这种优化

您最好使用union all:

注意:第二个WHERE子句可能需要考虑空值


每个子查询都将使用索引进行正确优化。

建议的和实际的执行计划是什么样子的?@SimonPrice:您是指EXPLAIN VERBOSE的输出吗?
SELECT *
FROM foo_db.foo_value
WHERE foo_id_a = 123456;
UNION ALL
SELECT *
FROM foo_db.foo_value
WHERE foo_id_b = 123456 AND foo_id_a <> 123456;