2015-11-08 117 views
0

索引的大小对于我的网店我有一个表,我使用了搜索:MySQL的减少巨额表

CREATE TABLE `store_search` (
    `term` varchar(50) NOT NULL DEFAULT '', 
    `content_id` int(10) unsigned NOT NULL, 
    `type` enum('keyword','tag') NOT NULL DEFAULT 'keyword', 
    `random` int(10) unsigned NOT NULL, 
    `saving` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`content_id`,`term`,`type`), 
    UNIQUE KEY `saving` (`term`,`saving`,`random`,`content_id`,`type`), 
    UNIQUE KEY `random` (`term`,`random`,`content_id`,`type`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED 

产品可以以两种方式列出:按随机顺序(基于栏random)或折扣(基于列saving)。过去的测试显示,使用UNIQUE订单的约束比使用标准索引与ORDER BY更有效。查询可以是这样的:

mysql> EXPLAIN SELECT content_id FROM store_search USE INDEX (random) WHERE term LIKE 'shirt%' AND type='keyword' LIMIT 2000,100; 
+----+-------------+--------------+-------+---------------+--------+---------+------+---------+--------------------------+ 
| id | select_type | table  | type | possible_keys | key | key_len | ref | rows | Extra     | 
+----+-------------+--------------+-------+---------------+--------+---------+------+---------+--------------------------+ 
| 1 | SIMPLE  | store_search | range | random  | random | 152  | NULL | 9870580 | Using where; Using index | 
+----+-------------+--------------+-------+---------------+--------+---------+------+---------+--------------------------+ 

这样我就可以防止ORDER BY条款(没有文件排序中,这种方法做)。

mysql> EXPLAIN SELECT DISTINCT x.content_id 
    -> FROM store_search x USE INDEX (saving) 
    -> INNER JOIN store_search y ON x.content_id=y.content_id 
    -> WHERE x.term LIKE 'shirt%' AND x.type='keyword' AND y.term LIKE 'blue%' AND y.type='keyword' 
    -> LIMIT 0,100; 
+----+-------------+-------+-------+-----------------------+---------+---------+--------------+----------+-------------------------------------------+ 
| id | select_type | table | type | possible_keys   | key  | key_len | ref   | rows  | Extra          | 
+----+-------------+-------+-------+-----------------------+---------+---------+--------------+----------+-------------------------------------------+ 
| 1 | SIMPLE  | x  | range | PRIMARY,saving,random | saving | 152  | NULL   | 11449970 | Using where; Using index; Using temporary | 
| 1 | SIMPLE  | y  | ref | PRIMARY,saving,random | PRIMARY | 4  | x.content_id |  20 | Using where; Using index; Distinct  | 
+----+-------------+-------+-------+-----------------------+---------+---------+--------------+----------+-------------------------------------------+ 

正如我所说的,这个解决方案是好的迄今:PRIMARY KEY用于自搜索多个术语时加入。我现在的问题是:目前这张表(〜500mio行)非常庞大,索引不再适合内存。这导致,INSERTUPDATE语句非常慢。数据需要23GB和索引消耗32GB,所以这张表的55GB。测试是可能的,但复制这张表时会消耗大量时间,但是有没有人可以减少索引大小? 我想将字符串列的排序转换为latin_1,但我可以合并一些索引吗?

+0

列** **中的不同值的数量限制为几个或者它们是否是真正的自由文本? – trincot

+0

这些确实是免费的文字。长期限制为50个字符。 – rabudde

+0

您实际需要向最终用户提供的记录数是否有限制?我的意思是,如果你得到10000场比赛,你是否真的需要全部提供? – trincot

回答

1

term LIKE 'shirt%'范围查找INDEX(term, ...)将不会通过term进行过滤,以便到达type或其他列。

这和其他基本索引原则在我的Index Cookbook中讨论。

因此... WHERE term LIKE 'shirt%' AND type='keyword'请求INDEX(keyword, term)。并且在过滤中添加任何其他列将无济于事。

但是,您所依赖的是涵盖。这是所有需要的列在单个索引中的位置。在这种情况下,可以在索引BTree中执行查询而不触及数据BTree。也就是说,增加额外的列可以是有益的。

多事情

SELECT content_id 
    FROM store_search USE INDEX (random) 
    WHERE term LIKE 'shirt%' 
     AND type='keyword' 
    LIMIT 2000,100; 
UNIQUE KEY `random` (`term`,`random`,`content_id`,`type`) 

怎么回事是一些:

  • 该指数是 “覆盖”。
  • 没有ORDER BY,所以输出可能首先按term排序(假设可能有多个以'shirt'开头的短语),并且仅次于random。这不是你想要的,但可能会发生作用。
  • LIMIT要求扫描2000 + 100行索引,然后退出。如果衬衫不够,它会停下来。这可能看起来“很快”。
  • UNIQUE可能是不相关的,并且对于插入是浪费的。

下一个查询让我们来剖析SELECT DISTINCT x.content_id ...

  • 您用DISTINCT的类似(可能更快)的代码替换了“filesort”。可能没有净收益;时间吧。
  • 如果有999件蓝色衬衫,它会找到全部999件,然后将它们分开,然后交付100件。
  • 如果没有ORDER BY,则无法预测将交付哪100个。
  • 由于您已经收集了所有999,因此添加ORDER BY RAND()不会增加太多开销。
  • 你真的想让'蓝绿'衬衫回归,但不是'浅蓝'吗? “衣服%”拿起“裤子裤子”呢?淫。

底线

  • PRIMARY KEY(type, term, content_id)更换3个索引。通过PK进入,你有效地“覆盖”。
  • 使用ORDER BY randomORDER BY RAND() - 请参阅哪个更适合您。 (后者是更随意!)
  • LIKE 'shirt%'

重新思考外卡底部的底线是,EAV架构设计很烂。我讨论这个further

+0

要更新这个问题:正如我所提到的,查询时间并不是那么糟糕。我尝试了不同索引的很多方法。缓慢的事情是更新表。所以我们决定使用Solr来检索必须在流中显示的内容ID,现在很好,因为巨大的search_ *表已经消失了。 – rabudde

+0

'innodb_buffer_pool_size'应该设置为_available_ RAM的大约70%。 –