我有一个带有全文的mysql表。每天它的大小将增加30K数据项。我担心当数据大小增加到许多GB时,查询速度会降低。我的情况允许我将搜索限制为最近的一百万个数据项。
首先我尝试partitioning table
,但mysql不同时支持fulltext
和partition
。
http://dev.mysql.com/doc/refman/5.5/en/partitioning-limitations.html
有些朋友建议我使用其他dbms产品,例如sphinx
,solr
或oracle
。但出于预算原因,我宁愿使用mySQL。 (原谅我的固执)。
那么,我该如何优化mysql全文表搜索?当数据量增大时,如何保持可接受的查询速度?
分桌? (然后使查询复杂)
仅限ID查询? SELECT * FROM table WHERE (MATCH (some_field) AGAINST ('+search_words' IN BOOLEAN MODE)) AND id>last_id-1000000 AND id<last_id Order By date DESC
另一个好建议?感谢。
答案 0 :(得分:5)
这是一种处理问题的方法。它不是超级漂亮,但它会非常有效。
创建表的两个副本。拨一个类似text_current
的内容,然后调用text_archive
之类的内容。
将新到达的数据行加载到text_current
。这样,您当前的数据将可用于搜索。
编写两个存储过程:一个称为copy_text
的内容,用于从text_current
中选择较旧的行并将其插入text_archive
,另一个称为purge_text
,用于删除来自text_current
的旧行。然后,从mySql作业运行这两个存储过程。
如果我是你,我会每晚03:00运行一次copy_text
工作,并复制前一天(午夜到午夜)任何时间到达的每件物品。
我会每周运行一次purge_text
工作,并清除超过35天的text_current
内的所有内容。 (每天30K记录获得100万条记录需要33.3天。)
这种将数据从当前表迁移到存档表的方法有一些方便的功能。
以下是record_date
列为unix时间戳时按日期选择记录的方法。如果您在任何一天运行此操作,它将从前一天的午夜选择记录,直到当天午夜的但不包括记录。
...
WHERE text_current.record_date >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 1 DAY))
AND text_current.record_date < UNIX_TIMESTAMP(CURDATE())
...
一天中运行此查询的时间无关紧要,它始终在午夜到午夜运行。这就是CURDATE()
的美丽 - 它意味着今天的午夜。 (NOW()
表示现在;它就像CURDATE()
但也有时间。但是你不希望这样,因为你想要在午夜到午夜进行归档。如果你使用{{ 1}}当您运行存储过程时,您会被小的不可预测性所困扰。
(不要试图将NOW()
运算符用于时间范围;它是包容性的,您希望时间范围的结束时间不包括在内。)
同样,如果您要删除超过35天的所有内容,请执行此操作。
BETWEEN
看看这是怎么回事?当您进行归档和清除时,无论插入的时间长短,您总是根据插入的日期选择记录。这就是我所说的确定性。