2

我知道如何添加全文索引并进行基本的布尔搜索...

ALTER TABLE products ADD FULLTEXT KEY myIndex (model, description);
SELECT * 
FROM   products 
WHERE  MATCH(model, description) AGAINST('myKeyword' in boolean mode);

但是,我想知道是否有可能做这样的事情......

我希望我的 SQL 检查“myIndex”是否存在,如果不存在,它应该自动获取现有列名并添加全文索引(注意 * 代替列名):

ALTER TABLE products ADD FULLTEXT KEY myIndex (*);

另外,在搜索索引时,我是否可以再次自动获取列名,而不必手动输入它们(再次注意 * 代替列名)...

SELECT * 
FROM  products 
WHERE MATCH(*) AGAINST('myKeyword' in boolean mode);

我不知道正确的语法,但这样的可能吗?我已经在谷歌上搜索了几个小时,但找不到答案。我知道我可以让 PHP 生成我需要的 SQL,但我想知道这是否可以使用严格的 SQL 来实现?

谢谢!

4

2 回答 2

4

根据您想要动态索引数据库的评论。这通常不是一个好主意。索引双刃剑是一把双刃剑。让我解释。

所以本质上,索引是磁盘上的一个数据结构,包含所有要索引的值。例如,假设您有一个包含 10 列的 1000 行表并且您索引 1 列,这个新索引也将包含 1000 个条目。它将包含该列的所有行值。然后将该索引写入磁盘,以便您可以读取它。

下次插入新行时,它必须插入到表和索引中。当您更新索引列时,它必须同时更新表和索引。从我在您的问题中可以看到,您想要动态索引几列。

因此,假设您有一个相当大的表,其中包含 10 000 000 行和 3 列,并且您将它们全部索引为需要索引的 30 000 000 个值。本质上,当您动态创建此索引时,服务器在索引表时会非常缓慢。此外,一旦完成,您的插入速度会变慢,索引列的更新也会变慢。一般的经验法则索引可以加快读取速度并减慢插入速度。

现在只是增加一点复杂性。您无法保证 MySQL 将使用新创建的索引。MySQL 使用内部统计信息来决定使用哪个索引。尽管在您的情况下,这可能不是问题,因为您使用的是全文索引。您可以在 MySQL 中强制使用索引,但这也不是最佳方式。

如果我可以提出建议,请不要这样优化。您正在尝试采用一种非常通用的优化方法,即在任何地方应用索引。而是启用慢查询日志并识别运行缓慢的查询。然后将这些查询与解释语句一起使用来确定如何优化这种情况。您最终将获得更少的索引并获得良好的读写速度平衡。

我希望这一切都有意义。

于 2013-07-17T00:02:46.737 回答
2

您可以通过这种方式检查全文索引是否存在:

SELECT DISTINCT index_name 
FROM INFORMATION_SCHEMA.STATISTICS
WHERE (table_schema, table_name) = ('mydatabase', 'products')
  AND index_type = 'FULLTEXT';

您可以通过以下方式获取该索引中的列:

SELECT column_name 
FROM INFORMATION_SCHEMA.STATISTICS
WHERE (table_schema, table_name) = ('mydatabase', 'products')
  AND index_type = 'FULLTEXT'
ORDER BY seq_in_index;

你不能使用MATCH(*). 列必须拼写出来,必须命名索引中的所有列,并且必须按照定义索引时的相同顺序命名它们。


我还应该注意,针对 information_schema 的一些查询似乎很慢,因为 InnoDB 通过从磁盘读取随机页面来对表和索引进行采样。也就是说,读取元数据会导致 I/O。您可以使用SET GLOBAL innodb_stats_on_metadata=0. 另见http://www.mysqlperformanceblog.com/2011/12/23/solving-information_schema-slowness/

于 2013-07-16T23:06:49.710 回答