我正在努力加快查询,找到所有已经购买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 BY
和HAVING
子句的工作查询:
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);
我可以使用哪些索引来加快查询速度?或者我应该更改我的查询?
更新
我发现另一个查询也有效,但它也太慢了。它已在上面添加。不过,在找到加速它的索引时可能会有所帮助。
答案 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));
答案 1 :(得分:0)
为什么在查询中没有使用聚合函数时使用group by? 如果您不想看到任何重复,请使用distinct