我创建了文件索引器,它只是将文件名插入到指定的表中。现在我正在考虑搜索文件名的最佳方法。表中可能有100000多个文件,因此性能很重要。
文件名可以是各种 - 长度为10,20,50或更多字符。至少目前,我的测试数据集中没有名称中包含空格的文件。用户可以进行部分搜索,例如查找' 1001'应该返回名称为10_1001_20_30_40_50的文件。
我目前的表结构:
CREATE TABLE `file` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`id_category` int(10) unsigned NOT NULL,
`filename` varchar(255) NOT NULL,
`file_ext` varchar(3) NOT NULL,
`date_added` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`,`id_category`),
KEY `idx_file_filename` (`filename`) USING BTREE,
KEY `fk_file_1_idx` (`id_category`),
FULLTEXT KEY `filename` (`filename`)
) ENGINE=MyISAM AUTO_INCREMENT=24974 DEFAULT CHARSET=utf8;
INSERT INTO `file` (`id`,`id_category`,`filename`,`file_ext`,`date_added`) VALUES (22474,14199,'095_98_1002_1003_148_98_1001_003','pdf','2016-03-19 19:02:12');
INSERT INTO `file` (`id`,`id_category`,`filename`,`file_ext`,`date_added`) VALUES (22475,14199,'095_98_1002_1003_148_98_1001_001','pdf','2016-03-19 19:02:11');
我已经尝试过使用MATCH()AGAINST(),但事实证明,如果你没有字符串中的空格并且想做"那么这不是一个好主意。如果字符串包含搜索"像:
SELECT id, filename FROM `file` WHERE MATCH(filename) AGAINST ('1002*' IN BOOLEAN MODE);
这不会归还我需要的东西。我考虑的是通过拆分所有文件名来使用FULLTEXT,同时导入3个长度(用户可以提供的最小字符串长度)用空格分隔的部分,它们使用如下查询:
SELECT * FROM `file` WHERE MATCH(filename) AGAINST ('100*' IN BOOLEAN MODE);
当然我可以保留文件名,并使用LIKE运算符:
SELECT * FROM `file` WHERE filename LIKE '%100%'
但是对于大型数据集使用LIKE存在很多负面意见。我很好奇,如果我的解决方案为文件名添加空格将是一个好主意。
答案 0 :(得分:0)
尝试使用FULLTEXT:需要空间,限制你(大部分)完全"单词",使用" short"单词,未命中和#34;停止单词"等。
if(true)
{
//to do
}
else
{
// to do
}
'虽然效率低,因为它必须测试每一行,但这正是您所需要的。
你暗示文件名的所有相关部分都是数字?而你只想测试整个零件?这将LIKE '%100%
搜索22_100_33
,22
和100
,但不会搜索33
,2
,10
等等?如果是这种情况,那么00
将无法正常工作。示例:LIKE
'。
101_1000
所以,也许你想建立一个倒排索引":对于LIKE '%100%
,你会在表格中有6行:10_1001_20_30_40_50
,10
等,以及其他列,或者一些用于加入1001
表的id。
答案 1 :(得分:0)
对于使用LIKE进行大型数据集存在很多负面意见
对你的情况来说,这可能是好的,我会先测试它。
如果你真的想要加速它,我可以想到一个选项,但牺牲将是巨大的 - 内存,插入时间,可维护性,灵活性,复杂性......你可以为后缀构建“倒排索引”。该表看起来像(伪代码):
@IBAction func okButton(sender: UIButton) {
resultOutputLabel.text == ""
}
并拥有此类数据
CREATE TABLE Pref(
prefix varchar(255) NOT NULL,
fileid bigint(20) unsigned NOT NULL,
CONSTRAINT [PK_Pref] PRIMARY KEY CLUSTERED
(
prefix ASC,
fileid ASC
))
它会在两列上都有聚簇主键。这样,它将按前缀排序,您可以将中缀搜索'095_98_1002_1003_148_98_1001_003', 22474
'95_98_1002_1003_148_98_1001_003', 22474
'5_98_1002_1003_148_98_1001_003', 22474
'_98_1002_1003_148_98_1001_003', 22474
'98_1002_1003_148_98_1001_003', 22474
...
'03', 22474
'3', 22474
更改为前缀搜索'%abcd%'
。然后查询将具有
'abcd%'
您只需制作触发器即可使其与主表保持同步。请注意,当您删除此表中的行时,您应该避免搜索没有指定前缀的fileid,否则性能将是一场灾难。