2016-03-19 92 views
1

Dosya adlarını yalnızca belirtilen tabloya ekleyen dosya dizinleyicisi oluşturdum. Şimdi dosya isimlerini aramanın en iyi yolunu düşünüyorum. Tabloda 100000+ dosya olabilir, bu nedenle performans önemlidir.Büyük veri kümesini sorgulamak için en uygun arama sorgusu ve yapısı

Dosya adı farklı olabilir - 10, 20, 50 veya daha fazla karakter uzunluğunda olabilir. En azından şimdilik, test veri kümemde adlarında boşluk bulunan dosya yok. Kullanıcı kısmi arama yapabilir, örneğin '1001' i arayan dosyayı 10_1001_20_30_40_50 adıyla döndürmelidir.

Benim şu anki tablo yapısı:

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'); 

ben KARŞI MATCH()() kullanmayı denedik, ancak bu dizede boşluk varsa ve istemediğiniz takdirde bu iyi bir fikir değil çıktı "dize arama içeriyorsa" gibi yap: "

SELECT id, filename FROM `file` WHERE MATCH(filename) AGAINST ('1002*' IN BOOLEAN MODE); 

Bu, ihtiyacım olanı geri getirmeyecek. (Min. Dize uzunluğu kullanıcı sağlayabilir):

SELECT * FROM `file` WHERE MATCH(filename) AGAINST ('100*' IN BOOLEAN MODE); 

Elbette bırakabilir Ne düşünüyorum 3 uzunluk içine boşluklarla ayrılmış parçaları ithalatı ve onları bu gibi sorguları kullanırken bölünmüş tüm dosya, tam metin kullanmaktır dosya adları olduklarını ve operatör GİBİ kullandıkça:

SELECT * FROM `file` WHERE filename LIKE '%100%' 

ama çok büyük veri kümeleri için GİBİ kullanmayla ilgili olumsuz görüşler vardır. Dosya adlarına boşluk ekleyerek çözümümün iyi bir fikir olacağını merak ediyorum. Tam metin kullanmaya çalışmak

+0

Ale Sadece 1002 mi arıyorsunuz, yoksa daha uzun dizileri (1002_1003) aramak ister misiniz? –

+0

Herhangi bir sorgu olabilir> = 3 karakter –

cevap

0

: 'vb, "kelimelerini dur" özlüyor,

LIKE '%100%, tam "kelimeleri" için (çoğunlukla) sınırlar, alanı gerektirir "kısa" sözleriyle verimsiz olur, verimsiz olsa bunun nedeni Her satırı test etmeli, ihtiyacın olan şey.

Dosya adlarının tüm ilgili bölümlerinin sayı olduğunu ima ediyorsunuz? Ve sadece tüm parçaları test etmek istediniz? Bu22, 100 ve 33 için aranacak, ancak 2, 10, 00, vb için aranacaktır? Durumun tamamı doğruysa, LIKE düzgün çalışmayacaktır. Örnek: 101_1000, LIKE '%100% 'tarafından yakalanacaktır.

Yani, belki bir "ters dizin" kurmayı planladıklarını: 10_1001_20_30_40_50, bir tablodaki bir 6 satırlarda yer alacaktır: 10, 1001, vs, ve ya sütunların kalanını veya bazı id (s) file tablosuna katılmak için. Büyük veri için GİBİ kullanımıyla ilgili olumsuz görüşler bir sürü var

+0

FT ile durumun silinmesi için teşekkür ederiz. Parçalar için test edeceğim ve parçalara geri ihtiyacım var, bu yüzden LIKE tamam. İçerisindeki dosya isimleri ve parçalar alfanümerik, çeşitli uzunluklarda olabilir, bu yüzden önerdiğiniz ters indeks yapısını kullanamıyorum. Soru hala açık - şimdilik LIKE kullanmalıyım gibi görünüyor. –

0

İlk ben test olacağını,

Şanslısınız, bu senin durum için yeterince iyi olurdu vardır ayarlar.

Eğer gerçekten hızlandırmak istiyorsanız, bir seçenek düşünebilirim, ama fedakarlıklar çok büyük olurdu - hafıza, ekleme süreleri, bakım, esneklik, karmaşıklık ... Ekler için "ters indeks" oluşturabilirsiniz.

CREATE TABLE Pref(
    prefix varchar(255) NOT NULL, 
    fileid bigint(20) unsigned NOT NULL, 

CONSTRAINT [PK_Pref] PRIMARY KEY CLUSTERED 
(
    prefix ASC, 
    fileid ASC 
)) 

ve her iki sütunlarda birincil anahtar kümelenmiş olurdu bu

'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 

gibi veriler var: Tablo (pseudocode) gibi görünecektir. Bu şekilde önek ile sipariş verilebilir ve '%abcd%' numaralı infix aramasını 'abcd%' önek araması olarak değiştirebilirsiniz. Sorgu sonra formu sadece ana tablonun ile senkronize tutmak için tetikleyicileri yapmak zorunda

SELECT id, filename FROM `file` 
WHERE id IN (SELECT fileid FROM Pref WHERE prefix like 'abcd%') 

olurdu. Bu tablodaki satırı sildiğinizde, önek belirtilmemiş dosya isminden kaçınmanız gerektiğini veya performansın bir felaket olacağını unutmayın.