سؤال

تم طرح تجسيدات مختلفة من هذا السؤال من قبل، لكنني اعتقدت أنني سأقدمها لقطة أخرى.

كان لدي تخطيط قاعدة بيانات رهيب. تم تقسيم كيان واحد (القطعة) إلى طاولين:

CREATE TABLE widgets (widget_id int(10) NOT NULL auto_increment)

CREATE TABLE widget_data ( widget_id int(10), field ENUM('name','size','color','brand'), data TEXT)

كان هذا أقل تلك المثالية. إذا أرادت العثور على وحدات واجهة مستخدم من اسم معين، اللون والعلامة التجارية، اضطررت إلى إجراء انضمام ثلاثي الاتجاه إلى جدول Widget_Data. لذلك قمت بتحويلها إلى نوع الجدول المعقول:

CREATE TABLE widgets (widget_id int(10) NOT NULL auto_increment, name VARCHAR(32),size INT(3),color VARCHAR(16), brand VARCHAR(32))

هذا يجعل معظم الاستفسارات أفضل بكثير. لكنه يجعل البحث أكثر صعوبة. اعتاد أن يكون ذلك إذا كنت أرغب في البحث في الحاجيات، فقل، "٪ أسود٪"، أود فقط SELECT * FROM widget_data WHERE data LIKE '%black%'. وبعد هذا من شأنه أن يعطيني جميع حالات الحاجيات السوداء باللون الأسود، أو مصنوعة من قبل صناعات بلاكويل، أو أيا كان. أود حتى أن أعرف بالضبط الميدان المتطابق، ويمكن أن تظهر ذلك لمستخدمي.

كيف يمكنني تنفيذ بحث مماثل باستخدام تخطيط الجدول الجديد؟ أنا يمكن أن تفعل بالطبع WHERE name LIKE '%black%' OR size LIKE '%black%'... ولكن هذا يبدو صديقا، وما زلت لا أعرف الحقول المتطابقة. يمكنني تشغيل استعلام منفصل لكل عمود أريد مطابقته، والذي من شأنه أن يعطيني جميع المباريات وكيفية مطابقة، ولكن هذا سيكون ضرب الأداء. أيه أفكار؟

هل كانت مفيدة؟

المحلول

لديك اثنين من المتطلبات المتضاربة. تريد البحث كما لو كانت جميع بياناتك موجودة في حقل واحد، ولكنك ترغب أيضا في تحديد حقل محدد مطابقته.

لا يوجد شيء خاطئ مع WHERE name LIKE '%black%' OR size LIKE '%black%'... التعبير. إنه بحث صالح تماما على الطاولة كما حددته. لماذا لا تحقق فقط من النتائج في التعليمات البرمجية لمعرفة أي واحد مطابق؟ انها الحد الأدنى من النفقات العامة.

إذا كنت تريد بناء جملة منظف ل SQL الخاص بك، فيمكنك إنشاء طريقة عرض على الجدول، مما يضيف حقل إضافي يتكون من تقليل الحقول الأخرى:

CREATE VIEW extra_widget_data AS
  SELECT (name, size, color, brand,
          CONCAT(name, size, color, brand) as all_fields)
  FROM widget_data;

ثم عليك إضافة فهرس في هذا الحقل، الأمر الذي يتطلب المزيد من المساحة، وقت وحدة المعالجة المركزية للحفاظ على الخ. لا أعتقد أنه يستحق كل هذا العناء.

نصائح أخرى

يمكنك تضمين جزء من WHERE التعبير في اختيار الأعمدة. علي سبيل المثال:

SELECT 
  *, 
  (name LIKE '%black%') AS name_matched,
  (size LIKE '%black%') AS size_matched
FROM widget_data 
WHERE name LIKE '%black%' OR size LIKE '%black%'...

ثم تحقق قيمة name_matched على جانب النص.

لست متأكدا من كيفية التأثير على الأداء. فال خالي من اختباره قبل الذهاب إلى الإنتاج

ربما تريد أن تنظر إلى إمكانية البحث النص الكامل MySQL، وهذا يتيح لك مطابقا ضد أعمدة متعددة من نوع Varchar.

http://dev.mysql.com/doc/refman/5.1/en/fulltext-search.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top