我在这里有一个非常蹩脚的问题,所以希望你们所有的MySQL专家都能为我解答这个问题:)
我有这种类型的表:
+--------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | PRI | NULL | |
| abc_1 | char(1) | NO | MUL | NULL | |
| abc_2 | char(2) | NO | MUL | NULL | |
| abc_3 | char(3) | NO | MUL | NULL | |
| abc_4 | char(4) | NO | MUL | NULL | |
| abc_5 | char(5) | NO | MUL | NULL | |
| abc_6 | char(6) | NO | MUL | NULL | |
| abc_7 | char(7) | NO | MUL | NULL | |
| abc_8 | char(8) | NO | MUL | NULL | |
| abc_9 | char(9) | NO | MUL | NULL | |
| abc_10 | char(10) | NO | MUL | NULL | |
+--------+------------------+------+-----+---------+-------+
此表上有很多(数百万)记录。
所有查询如下:
SELECT `id` FROM `tbl` WHERE `abc_1` = 'a' LIMIT 10;
SELECT `id` FROM `tbl` WHERE `abc_2` = 'zz' LIMIT 10;
SELECT `id` FROM `tbl` WHERE `abc_3` = 'xxx' LIMIT 10;
等等。
表有InnoDB引擎,abc
列的排序规则为latin1_general_ci
。
所以我的问题很简单:我应该添加哪个索引以使这些类型的查询运行得更快?
仅限单列(例如abc_1
,abc_2
等),
两列(例如:id
和abc_1
,id
和abc_2
等等)
或两列的顺序相反(例如:abc_1
和id
,abc_2
和id
)?
我想最后一个变体是最好的(abc_1
+ id
)。
我可以测试和测试所有变体,但由于它是大表,因此需要花费大量时间来创建新索引,所以我想首先询问您的意见。
也许有人可以建议任何缓存技术如何更快地运行这些类型的查询,而不直接涉及MySQL?
我听说过这种类型的查询可以使用Sphinx,例如:添加abc
列作为属性?也许somone有经验吗?
提前谢谢大家!
答案 0 :(得分:0)
这些查询的最佳索引是复合索引:table(abc_1, id)
,table(abc_2, id)
,table(abc_3, id)
(依此类推)。我相信这是你的最后一个选择。
这些索引“涵盖”您建议的查询。这意味着索引本身可以用于查询,而不是从数据页加载数据。
如果您混合使用所有这些查询,那么您需要确保有足够的内存将索引存储在内存中。
答案 1 :(得分:0)
我会将id设为主键,然后单独索引abc_ *列。 MySQL中的二级索引与其对应的主键值一起存储,因此实际上它们可以"参见"主键。在空间优化和避免大量冗余方面,我只需将id作为主键,然后单独索引abc_ *列。
就性能而言,你拥有的两个最大的杠杆是缓冲池http://dev.mysql.com/doc/refman/5.6/en/innodb-buffer-pool.html ...特别是innodb_buffer_pool_size和innodb_buffer_pool_instances)以及你自己提交的查询。如果您的abc_ *列已编制索引(并且id是主键),则您建议的查询将非常有效。但是你要注意慢速查询日志,并且可能安装Percona MySQL并使用他们的pt-query-digest工具来分析你的慢查询(例如http://www.percona.com/doc/percona-toolkit/pt-query-digest.html)。后者更具可选性,考虑到您提出的疑问,首先可能没有必要。
不过,我考虑过的一件事就是abc_ *列的长度。如果它们相当长,您可以尝试应用它们的MD5,或者将数据标准化一点,并简单地存储id(将实际文本值放在查找表中)。后者不一定是必要的(原谅那个精彩的句子),但如果我在abc_ *列中有特别长的文本值,我可能会考虑它。答案 2 :(得分:0)
如果您没有交叉 - 即每列中的值,则每列都是唯一的,例如' zz'只能在abc_2中找到,而不是第3列等。 ...然后建议MySQL中的全文索引可以正常工作。您只进行单字查找,因此速度非常快。甚至是innodb中新的全文支持。 (全文中使用的倒排索引非常适合单字查找)
如果您确实需要将结果限制为特定列,那么外部搜索引擎可能会更好。你建议使用Sphinx可以工作,但大多数人都可以满足这些简单的要求。外部索引的一个很好的功能,可以在不更改数据库表的情况下设置索引,因此可以在表上设置一个sphinx索引,不用触摸您的实际表。 (在Sphinx中,您不需要将列作为属性,将它们保留为字段,您仍然可以进行全文查询。使用较少的内存,索引将更快。) ... sphinx将运行此类查询,几乎始终不到1毫秒,无论索引大小如何,以及非常适度的服务器。