类似术语%ORDER BY int的MySQL查询优化
我的问题是在使用前缀匹配时,如何处理VARCHAR上的MySQL索引和int列。 e、 g.如果我有这样的疑问:类似术语%ORDER BY int的MySQL查询优化,mysql,indexing,query-optimization,Mysql,Indexing,Query Optimization,我的问题是在使用前缀匹配时,如何处理VARCHAR上的MySQL索引和int列。 e、 g.如果我有这样的疑问: SELECT * FROM tbl WHERE name LIKE 'query%' ORDER BY weight DESC LIMIT 5 考虑到我有一个索引one name->weight,该索引是否需要查找前缀query的所有外观,然后按顺序排序,或者即使使用前缀匹配(%),他是否仍将交叉计算索引化。我对此感到困扰,因为对于流行名称(例如query=john),我可能会发现
SELECT * FROM tbl WHERE name LIKE 'query%' ORDER BY weight DESC LIMIT 5
考虑到我有一个索引one name->weight,该索引是否需要查找前缀
query
的所有外观,然后按顺序排序,或者即使使用前缀匹配(%),他是否仍将交叉计算索引化。我对此感到困扰,因为对于流行名称(例如query=john),我可能会发现自己搜索john的所有外观需要很长时间,这会使限制无效,并且在处理大型数据集时,查询变得缓慢。你问了另一个问题“创建一个最适合通过4000万个名称进行通配符搜索的索引”。好的,您有4000万条记录
现在考虑以下公式:
x = COUNT(DISTINCT values in a column) / COUNT(values in a column)
列上的索引更好,x越接近1。如果为1,则所有值都不同,没有重复项,因此索引速度相当快
现在您正在寻找“john%”。这是4个字母和一个开放式结尾。哪些字母不重要,您的DB必须处理26*26*26*26=456976个不同的值。将其放入上述公式和4000万条记录中。您得到的x
为00114244
我不知道阈值是多少,但IIRC是0,1或其他。所以,如果你x
高于0,1,则使用索引,如果它较低,则不使用
为什么会这样?使用索引甚至会减慢速度,因为您的数据库必须查看索引,查看该索引中物理硬盘上的哪个位置有合适的记录,然后获取该记录。因此,当x低于10%时,只需扫描整个表就可以加快速度
总而言之:只使用一个像您这样的弱索引过滤4000万条记录是毫无用处的。前提是
'query'
的长度等于或短于name
的索引前缀:
(名称、权重)
上的复合b树
索引将按名称
排序,然后按权重
排序。概念上:
+---------+--------+---------+
| name(7) | weight | address |
+---------+--------+---------+
| queryaa | 500 | 0x1.... |
| queryaa | 500 | 0xe.... |
| queryaa | 498 | 0x8.... |
| queryaa | 491 | 0xb.... |
| queryaa | 486 | 0xc.... |
| queryaa | 430 | 0x3.... |
| queryab | 600 | 0x2.... |
| queryab | 592 | 0x7.... |
| queryab | 550 | 0x4.... |
| queryab | 321 | 0xa.... |
| queryab | 321 | 0x6.... |
| queryab | 304 | 0x9.... |
| queryab | 297 | 0x5.... |
| querybc | 800 | 0xd.... |
: : : :
如果
'query'
比name
的索引前缀长,那么MySQL必须在上面的步骤1中查找表,以便充分过滤随后排序的记录。:“查询每个表索引,除非优化器认为使用表扫描更有效,否则将使用最佳索引。曾经,根据最佳索引是否跨越表的30%以上使用扫描,但固定百分比不再决定使用索引还是扫描。优化器现在更加复杂,它的估计基于其他因素,如表大小、行数和I/O块大小。“谢谢eggyal,所以是0,3,信息有点过时。无论如何,我认为我的观点仍然有效。同意,我只是补充说明。)@tombom您会推荐什么方法?如果没有关于您的模式、用例等的详细信息,很难说清楚。也许查找表是一个带有散列索引的选项。最简单的方法当然是用适当的复合索引尽可能多地过滤查询,但是所有这些都是要问和考虑的,你最好问一个不同的问题。所以,实际上你需要找到匹配查询的所有单词。像“john%”这样的按重量排序的查询对他来说真的很难吗?@Noam:我是说这取决于索引前缀的长度。
+---------+--------+---------+
| name(7) | weight | address |
+---------+--------+---------+
| querybc | 800 | 0xd.... | --> fetch from table
| queryab | 600 | 0x2.... | --> fetch from table
| queryab | 592 | 0x7.... | --> fetch from table
| queryab | 550 | 0x4.... | --> fetch from table
| queryaa | 500 | 0x1.... | --> fetch from table
+---------+--------+---------+