SQLite优化多选插入
我已经使用SQL很多年了,但很少有比简单的插入和选择等更简单的了。。。所以我不是SQL专家。我想知道我是否可以得到一些帮助来优化我在SQLite上执行的更复杂的SQL语句,从PHP到PDO 这句话似乎是正确的,只是似乎比我预期的要花更长的时间(或者我只是期望太多) 这是SQL:SQLite优化多选插入,sql,sqlite,Sql,Sqlite,我已经使用SQL很多年了,但很少有比简单的插入和选择等更简单的了。。。所以我不是SQL专家。我想知道我是否可以得到一些帮助来优化我在SQLite上执行的更复杂的SQL语句,从PHP到PDO 这句话似乎是正确的,只是似乎比我预期的要花更长的时间(或者我只是期望太多) 这是SQL: INSERT OR IGNORE INTO MailQueue(SubscriberID, TemplateID) SELECT Subscribers.ID, '1' AS TemplateID FRO
INSERT OR IGNORE INTO MailQueue(SubscriberID, TemplateID)
SELECT Subscribers.ID, '1' AS TemplateID
FROM Subscribers
INNER JOIN SubscriberGroups ON Subscribers.ID=SubscriberGroups.SubscriberID
WHERE SubscriberGroups.GroupID IN ('1', '2', '3')
AND Subscribers.ID NOT IN
(
SELECT Subscribers.ID FROM Subscribers
INNER JOIN SubscriberGroups ON Subscribers.ID=SubscriberGroups.SubscriberID
WHERE SubscriberGroups.GroupID IN ('4', '5', '6')
);
我得到的是一个订户列表,在一个或多个组中。我想将订阅者添加到邮件队列中,选择属于一个或多个组(1,2,3)的订阅者,但排除也属于另一组组(4,5,6)的订阅者
首先,上面的SQL是典型的如何做到这一点的
第二,我应该具备哪些指标才能使这项工作尽可能有效
目前,在avg spec LAMP上浏览大约5000条订户记录(和少数组)需要大约30秒
一天结束时,性能并不是那么关键,但我想更好地理解这一点,因此任何见解都会受到极大的赞赏
Brad额外的加入很可能会让你丧命。如果您这样做:
SELECT Subscribers.ID, '1' AS TemplateID
FROM Subscribers
WHERE EXISTS( SELECT *
FROM SubscriberGroups
WHERE Subscribers.ID=SubscriberGroups.SubscriberID
AND SubscriberGroups.GroupID IN ('1', '2', '3') )
AND NOT EXISTS( SELECT *
FROM SubscriberGroups
WHERE Subscribers.ID=SubscriberGroups.SubscriberID
AND SubscriberGroups.GroupID IN ('4', '5', '6')
);
您还需要确保在SubscriberGroups(SubscriberID,GroupID)上有一个索引
我猜订阅者已经在ID上有了索引,对吗
编辑:
另一种选择,可能更快,也可能更快。查看每个查询计划以查看
这可能是一个单索引扫描,它可能比两个索引查找更快,但它取决于SQLite的优化器
SELECT Subscribers.ID, '1' AS TemplateID
FROM Subscribers
INNER JOIN( SELECT SUM( CASE WHEN GroupID IN('1', '2', '3') THEN 1 ELSE 0 END ) AS inGroup,
SUM( CASE WHEN GroupID IN('4', '5', '6') THEN 1 ELSE 0 END ) AS outGroup,
SubscriberID
FROM SubscriberGroups
WHERE SubscriberGroups.GroupID IN ('1', '2', '3', '4', '5', '6' )
) SubscriberGroups
ON Subscribers.ID=SubscriberGroups.SubscriberID
AND inGroup > 0
AND outGroup = 0
编写SQL的另一种方法可能更快(我没有要测试的SQLite): 马特的方法也应该很有效。这完全取决于SQLite决定如何创建查询计划
另外,请注意我的评论。如果这些数据类型在数据库中定义为INT数据类型,那么在这两种不同的数据类型之间需要进行一些额外的转换处理。如果它们是数据库中的字符串,有什么原因吗?这些列中有非数值吗?谢谢Matt,太好了。您的第一个解决方案将时间从30秒减少到大约5或6秒,这就足够了。我没有尝试第二种选择,因为我并不真正理解它,但如果它成为一个问题,我会记住它。再次感谢Hanks Tom,你在引用的ID上是对的。。。不知道我为什么把它们放在那里。我没有尝试你的建议,因为马特的似乎很好,而你的似乎错过了排除组部分(4,5,6)。无论如何谢谢你!实际上更仔细地看,我意识到其中一个ID列没有声明为整数,这就是我需要引号的原因。SQLite对类型并不挑剔,这就是我错过它的原因。更改为整数并删除引号,它现在运行约1/2秒。谢谢我的孩子应该照顾孩子。你测试过了吗?这就是整个左联的意义所在。在WHERE子句中检查联接表中的NOTNULL列,如果该列为NULL,则知道不存在匹配项。
SELECT
S.ID,
'1' AS TemplateID -- Is this really a string? Does it need to be?
FROM
Subscribers S
LEFT OUTER JOIN SubscriberGroups SG ON
SG.SubscriberID = S.ID
WHERE
SG.SubscriberID IS NULL AND
EXISTS
(
SELECT
*
FROM
SubscriberGroups SG2
WHERE
SG2.SubscriberID = S.ID AND
SG2.GroupID IN ('1', '2', '3') -- Again, really strings?
)