优化的 SQL 查询
Posted
技术标签:
【中文标题】优化的 SQL 查询【英文标题】:Optimized SQL Query 【发布时间】:2012-03-24 05:21:07 【问题描述】:表架构
对于这两个表,CREATE 查询如下:
表 1:(file_path_key,dir_path_key)
创建表 Table1(file_path_key varchar(500), dir_path_key varchar(500), 主键(file_path_key)) engine = innodb;
例如,file_path_key = /home/playstation/a.txt dir_path_key = /home/playstation/
Table2:(file_path_key,hash_key)
创建表 Table2(file_path_key varchar(500) not null, hash_key bigint(20) 不为空,外键 (file_path_key) 引用 Table1(file_path_key) on update cascade on delete cascade) 引擎 = innodb;
目标:
Given a hash value *H* and a directory string *D*, I need to find all those
hashes which equal to *H* from Table2, such that, the corresponding file entry
doesn't have *D* as it's directory.
在这种特殊情况下,Table1 有大约 40,000 个条目,Table2 有 5,000,000 个条目,这使得我当前的查询非常慢。
select distinct s1.file_path_key from Table1 as s1 join (select * from Table2 where hash_key = H) as s2 on s1.file_path_key = s2.file_path_key and s1.dir_path_key !=D;
【问题讨论】:
密钥的(潜在)大小肯定没有帮助。看起来您不需要潜在的键范围 - 您会考虑切换到您加入的自动生成主键吗?这应该会大大减少你的表的大小——一方面,这意味着file_path_key
可以变成file
(这可能会减少不匹配)。太糟糕了,您没有使用支持递归 CTE 的 RDBMS - 它们非常适合文件夹结构。
【参考方案1】:
子选择确实会不必要地减慢您的查询速度。
您应该删除它并用简单的连接替换它,将所有与连接无关的条件下推到 WHERE 子句中。
您还应该在 Table1.dir_path_key 和 Table2.hash_key 列上添加索引:
ALTER TABLE Table1
ADD INDEX dir_path_key dir_path_key(255);
ALTER TABLE Table2
ADD INDEX hash_key (hash_key);
尝试这样的查询:
select distinct s1.file_path_key
from Table1 as s1
join Table2 as s2 on s1.file_path_key = s2.file_path_key
where s1.dir_path_key !=D
and s2.hash_key =H;
【讨论】:
当然,我会试试这个。如何为列添加索引? 我添加了用于创建索引的示例 DDL。请注意,这会将表锁定几分钟,因此您不应在实时生产数据库上执行此操作。 好吧,表格一旦填入我的用例就不会更新。所以这应该不是问题? 对不起,我来晚了,但添加索引效果很好! SELECT 查询现在快得多了!谢谢艾克!【参考方案2】:我建议先从 Table2 中选择条目到临时表中:
SELECT * FROM Table2 INTO #Temp WHERE hash_key = H
然后在 SELECT 语句中加入临时表:
select distinct s1.file_path_key from Table1 as s1 join #Temp as s2 on s1.file_path_key = s2.file_path_key and s1.dir_path_key !=D;
【讨论】:
这对查询执行时间有影响吗? 我在过去将其付诸实践时通常会注意到一个相当大的差异。以上是关于优化的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章