【问题标题】:SQLite3 how do I use indices?SQLite3 如何使用索引?
【发布时间】:2014-06-27 15:35:52
【问题描述】:

我正在研究 SQLite3 索引。

这是公司的表格:

CREATE TABLE COMPANY(
ID INT PRIMARY KEY     NOT NULL,
NAME           TEXT    NOT NULL,
AGE            INT     NOT NULL,
ADDRESS        CHAR(50),
SALARY         REAL
);

INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (1, 'Paul', 32, 'California', 20000.00 );

INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (2, 'Allen', 25, 'Texas', 15000.00 );

INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );

INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );

INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (5, 'David', 27, 'Texas', 85000.00 );

INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)
VALUES (6, 'Kim', 22, 'South-Hall', 45000.00 );

INSERT INTO COMPANY VALUES (7, 'James', 24, 'Houston', 10000.00 );

================================================ ========

SELECT * FROM COMPANY;

结果:

1|Paul|32|California|20000.0
2|Allen|25|Texas|15000.0
3|Teddy|23|Norway|20000.0
4|Mark|25|Rich-Mond |65000.0
5|David|27|Texas|85000.0
6|Kim|22|South-Hall|45000.0
7|James|24|Houston|10000.0

让我们创建一个索引salary_index,

CREATE INDEX IF NOT EXISTS salary_index on COMPANY (SALARY);

它有什么作用以及如何使用它?

这次我在删除旧的索引后做一个这样的索引:

CREATE INDEX IF NOT EXISTS salary_index on COMPANY (SALARY) 
WHERE SALARY > 50000;

添加索引后,我做了:

SELECT * FROM COMPANY;

本以为我只会看到薪水高于 50000 的人,但我看到的人却低于 50000。

我也尝试过这样做:

SELECT * FROM COMPANY INDEXED BY salary_index;

然后我得到错误:没有查询解决方案 显然我必须这样做: SELECT * FROM COMPANY INDEXED BY Salary_index WHERE SALARY > 50000; 其中条件必须与索引中的条件相同。

那么……我该如何使用索引?

【问题讨论】:

    标签: sqlite indexing indices


    【解决方案1】:

    索引永远不会改变查询的含义。 他们可以做的是加快您的一些查询;如果可能,它们会自动使用。

    索引是有用的

    • 在索引列上通过比较查找记录:

      SELECT * FROM Company WHERE Salary = 20000.0;
      SELECT * FROM Company WHERE Salary BETWEEN 40000 AND 80000;
      

      其中还包括索引列上的连接;和

    • 排序记录:

      SELECT * FROM Company ORDER BY Salary
      

      其中还包括 GROUP BY 和 DISTINCT。

    详见文档:
    Query Planning
    The SQLite Query Planner

    【讨论】:

      【解决方案2】:

      这是我与一位代码大师的对话(感谢 S.P.):

      索引通常是提高性能的工具。 如果您没有某个字段的索引,则对该字段的查询将需要对表进行完整的顺序扫描。如果表很小,这不是问题,但是如果您有数万行或更多行,那么完整的顺序扫描就太慢了。

      所以如果要获取工资

      SELECT * FROM COMPANY WHERE SALARY < 50000
      

      只要 SALARY 字段被索引,它就会自动使用正确的索引

      所以如果我们有两个像这样的索引

      CREATE INDEX salary_index WHERE salary < 50000;
      CREATE INDEX age_index WHERE age < 40;
      

      然后我们运行类似的查询

      SELECT * FROM COMPANY WHERE salary < 50000 AND age < 40;
      

      它会自动使用上述 2 个索引进行查询。

      在大多数 RDBMS 中,可以在单个查询中使用多个索引,是的,如果它们适用,它们会自动使用。但可能对此有限制,并且它们是特定于 RBDMS 的。但更好的办法是创建一个包含多个字段的索引。

      在最佳情况下,您可以在单个索引中包含查询所需的所有字段 因此,如果您想要收入超过 50 000 美元且年龄小于 40 岁的员工 你可以这样定义一个索引:

      CREATE INDEX company_salary_age ON company (salary, age);
      

      字段的顺序很重要。此索引可用于具有关于薪水或薪水和年龄的 WHERE 子句的查询,但不是没有薪水的年龄。即索引的任意数量的字段只要在索引的前面是连续的就可以使用也就是在查询中可以从末尾省略字段,但不能在开头或中间。

      【讨论】:

      • 不,大多数数据库每个表只使用一个索引。在您的双索引示例中,数据库的查询优化器将选择要使用的索引。此外,构建部分索引(并非所有数据库都支持它们)以匹配未来的查询是不常见的。 salary 上的完整索引在响应您的查询时作为部分索引同样有用(并且能够满足您的部分索引无法满足的查询)。
      • 对不起,我发表了错误的评论。 SQLite3 支持多个索引,我的问题是关于 SQLite3。
      • 这是不正确的。 SQLite 将允许您创建多个索引(所有数据库都这样做),它允许您创建多列索引。但它只会为每个表应用一个索引,用于查询中对该表的行过滤操作。您链接的文档(在基本层面上)解释了 SQLite 如何选择要使用的索引。
      • 选择最优索引是一个复杂的问题,因为它不仅取决于索引的定义和查询的性质,还取决于内容的指数。具有 1000 个均匀分布值的索引优于仅具有 2 个值的索引,或者如果值不均匀分布的具有 1000 个值的索引(除非搜索不常见值之一)。数据库尝试找到最佳索引并且几乎在所有情况下都成功。
      • 如果您希望发出包含 both salarysalaryindex 的可优化表达式的查询,并且需要这些查询尽可能快,那么维持复合指数。否则维护复合索引的开销就白白浪费了。
      猜你喜欢
      • 1970-01-01
      • 2020-09-04
      • 1970-01-01
      • 2018-12-16
      • 2016-08-21
      • 1970-01-01
      • 1970-01-01
      • 2012-08-12
      相关资源
      最近更新 更多