SQL:如何使用索引加速查询

时间:2014-01-23 05:48:04

标签: sql sqlite indexing query-optimization

我正在努力加快查询,找到所有已经购买1970年以前生产的摩托车的客户,并购买了2010年以后生产的另一辆摩托车。由于我的查询运行速度非常慢,我认为我需要帮助才能找到更好的索引。我的尝试记录如下:

表格

CREATE TABLE CUSTOMER (
  id int PRIMARY KEY, 
  fname varchar(30),     
  lname varchar(30)
);

CREATE TABLE MOTORCYCLE (
  id int PRIMARY KEY, 
  name varchar(30), 
  year int -- Manufactured year
);

CREATE TABLE SALES (
  cid int,
  mid int,
  FOREIGN KEY(cid) REFERENCES CUSTOMER(id), 
  FOREIGN KEY(mid) REFERENCES MOTOCYCLE(id),
  PRIMARY KEY(pid, mid, role)
);

索引

这是我的索引(我有点猜测这些,但这是我的尝试):

CREATE UNIQUE INDEX customerID on CUSTOMER(id);
CREATE INDEX customerName on CUSTOMER(fname, lname);

CREATE UNIQUE INDEX motorcycleID on MOTORCYCLE(id);
CREATE INDEX motorcycleName on MOTORCYCLE(name);
CREATE INDEX motorcycleYear on MOTORCYCLE(year);

CREATE INDEX salesCustomerMotorcycleID on SALES(cid, mid);       
CREATE INDEX salesCustomerID on SALES(cid);
CREATE INDEX castsMotorcycleID on SALES(mid);

查询

我在1970年以后和2010年之后找到购买自行车的客户的询问是:

SELECT fname, lname
FROM (SALES INNER JOIN CUSTOMER ON SALES.cid=CUSTOMER.id) INNER JOIN MOTORCYCLE ON MOTORCYCLE.id=SALES.mid
GROUP BY CUSTOMER.id
HAVING MIN(MOTORCYCLE.year) < 1970 AND MAX(MOTORCYCLE.year) > 2010;

这是另一个可以避免GROUP BYHAVING子句的工作查询:

SELECT DISTINCT C.id, fname, lname
FROM (CUSTOMER as C inner join (SALES as S1 INNER JOIN MOTORCYCLE as M1 ON M1.id=S1.mid) on C.id=S1.cid) inner join (SALES as S2 inner join MOTORCYCLE as M2 on S2.mid=M2.id) on C.id=S2.cid
WHERE (M1.year < 1970 AND M2.year > 2010);

我可以使用哪些索引来加快查询速度?或者我应该更改我的查询?

更新

我发现另一个查询也有效,但它也太慢了。它已在上面添加。不过,在找到加速它的索引时可能会有所帮助。

2 个答案:

答案 0 :(得分:1)

当您使用EXPLAIN QUERY PLAN签出查询时,您会发现在这两种情况下,数据库会在筛选出不需要的记录(包含不需要的年份)之前查找许多相关记录。

以下查询在匹配前查找摩托车ID;哪一个更快取决于您的数据的细节,必须由您测量:

SELECT *
FROM Customer
WHERE EXISTS (SELECT 1
              FROM Sales
              WHERE cid = Customer.id
                AND mid IN (SELECT id
                            FROM Motorcycle
                            WHERE year < 1970))
  AND EXISTS (SELECT 1
              FROM Sales
              WHERE cid = Customer.id
                AND mid IN (SELECT id
                            FROM Motorcycle
                            WHERE year > 2010));

SELECT *
FROM Customer
WHERE EXISTS (SELECT 1
              FROM Sales AS s1
              JOIN Sales AS s2 ON s1.cid = s2.cid
              WHERE s1.cid = Customer.id
                AND s1.mid IN (SELECT id
                               FROM Motorcycle
                               WHERE year < 1970)
                AND s2.mid IN (SELECT id
                               FROM Motorcycle
                               WHERE year > 2010));

SQL Fiddle

答案 1 :(得分:0)

为什么在查询中没有使用聚合函数时使用group by? 如果您不想看到任何重复,请使用distinct