我在 mysql 连接方面的知识陷入了僵局,而且我尝试执行的查询花费的时间太长......虽然我自己学习 mysql 的时间很短,但我已经花时间阅读关于索引和连接的机制,做了很多谷歌搜索并尝试了几种不同的查询格式。无济于事,我需要帮助。
首先,我会说我的数据库目前正在针对选择查询的速度进行优化。我知道我有太多的索引......我学习mysql的理论是制作一些太多的索引并检查mysql优化器为我的目的选择什么(通过使用解释确定),然后确定它为什么选择所说的索引.
无论如何,我有四个表:table1,table2,table3,table4 ...
table1.ID1 是主键,table1 中的其他数据可能会分成 table2 中的多个内容。table2.ID1 标识 table1 中基于内容表单 table1 table2 构建的每个条目。ID2 是 table2 table3 的主键。ID2 标识 table3 中基于内容表单 table2 table3 构建的每个条目。ID3 是 table3 table4 的主键。 ID3 标识 table4 中基于内容表单 table3 构建的每个条目
并非table1中的每个条目在table2中都有对应的数据,同样table2到table3,table3到table4。
我需要做的是检索出现在日期范围内的 ID2 的不同值,并且仅当 table2 内容最终出现在 table4 中时。我面临的挑战是只有 table1 有一个日期列,我只需要也出现在 table4 中的条目。
以下查询大约需要 2 分钟。
select table2.ID2 from table1
left join table2 on
table1.ID1 = table2.ID1
left join table3 on
table3.ID2 = table2.ID2
left join table4 on
table4.ID3 = table3.ID3
where table1.Date between "2012-03-11" and "2012-03-18
通过对上述查询使用解释,我认为没有理由需要这么长时间。
+----+-------------+--------------+-------+----------------------+----------+---------+------------------------------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+-------+----------------------+----------+---------+------------------------------+-------+--------------------------+
| 1 | SIMPLE | table1 | range | ... | Datekey | 9 | NULL | 17528 | Using where; Using index |
| 1 | SIMPLE | table2 | ref | ... | ID1key | 8 | mydata.table1.POSTID | 1 | |
| 1 | SIMPLE | table3 | ref | ... | ID2key | 8 | mydata.table2.SrcID | 20 | |
| 1 | SIMPLE | table4 | ref | ... | ID3key | 8 | mydata.table3.ParsedID | 10 | Using index |
+----+-------------+--------------+-------+----------------------+----------+---------+------------------------------+-------+--------------------------+
我已经用“...”替换了可能键的名称,因为它并不那么重要。在任何情况下,都会选择一个键。
此外,查询结果集中的行数比解释结果集中声称的匹配 17528 行要多得多。怎么可能更多??
我究竟做错了什么?我也尝试过内部连接,但没有运气。我解释我的查询的方式是一个 4 向维恩图,具有重叠标准的行数很少,并通过日期范围上的索引进一步优化。
如果我添加'distinct(table2.ID2)',我至少会得到我想要的结果集,但为什么我得到的结果集比我预期的要长得多,为什么要花这么长时间?
抱歉,如果我的问题的任何部分模棱两可,我很乐意根据需要澄清。
谢谢,布赖恩
编辑:
所有索引都引用 BIGINT 列,因为我希望我的数据库变得相当大并且需要相当多的唯一行标识符......也许 bigint 是矫枉过正并且减小该列的大小和/或索引会进一步加快速度.
这是我的最终解决方案,基于以下接受的答案:
select ID2 from table2
where exists
(select 1 from table1 r
where table1.Date between "2012-03-11" and "2012-03-18" and table2.ID1 = table1.ID1
)
and exists
(select 1 from table3
where exists
(select 1 from table4 where table4.ID3 = table3.ID3)
)
此外,我意识到我缺少一个多字段索引,关联 table2.ID1 和 table2.ID2... 添加此索引后,此语句在大约 11 秒内返回,并返回大约 20,000 行。
考虑到我的每个表中的行数,我认为这是合理的 table1: ~480,000 table2: ~480,000 table3: ~6,000,000 table4: ~60,000,000
这听起来有效吗?在我确认这是我应该期待的最佳表现后,我会接受答案。我在 Xeon 3GHz 系统上运行 3gb 内存、ubuntu 12.04、mysql 5.5.24