# پایگاه‌های داده > NoSQL >  دیتابیس مناسب برای جستجوگر

## ferodo

سلام
برای یک سیستم جستجوگر چه دیتابیسی رو پیشنهاد میکنید.
قبلا با آپاچی سولر postgresql , mysql , mongodb
کار کردم و تست کردم
البته اپاچی سولر رو با دروپال تست کردم و
در کار با postgresql , mysql ترجبه ی زیادی دارم
اما از سه مدل پایگاه داده nosql هنوز اطلاعات زیادی ندارم و دارم مطالعه میکنم
بیشتر پست های این تالار رو خوندم اما اطلاعات بیشتر بازهم نیازه

خواستم نظر شما رو در مورد انتخاب یک پایگاه داده مناسب برای یک موتور جستجوگر بدونم
توی انتخاب این پایگاه داده برام این موارد خیلی مهمه 1 سرعت بسیار بالا 2 امنیت
+ یک پایگاه داده دیگه هم نیاز دارم
یک پایگاه داده هم میخام که سرعت نوشتنش خیلی بالا باشه 2 امنیت بالا باشه (البته تو این یکی سرعت جستجو اصلا مهم نیست فقط سرعت نوشتن)
یک مورد دیگه هم تا از قلم نیفتاده قابلیت پهن شدن روی چن تا سرور رو داشته باشه البته تا اینجا میدونم برای nosql بیشتر از hadoop بیشتر استفاده میشه

----------


## cups_of_java

امنیت رو (اگر Security منظورتونه) در لایه دیتابیس نباید جستجو کنید.

برای کاری که میخواید انجام بدید می تونید از CouchDB یا Couchbase بعنوان دیتابیس استفاده کنید چون سرعت نوشتن بالایی دارن و برای جستجو هم حتمن ElasticSearch رو یه امتحان کنید.
هم Couchbase هم ElasticSearch امکانات Clustering و Sharding خوبی در اختیارتون قرار میدن.

----------


## ferodo

> امنیت رو (اگر Security منظورتونه) در لایه دیتابیس نباید جستجو کنید.
> 
> برای کاری که میخواید انجام بدید می تونید از CouchDB یا Couchbase بعنوان دیتابیس استفاده کنید چون سرعت نوشتن بالایی دارن و برای جستجو هم حتمن ElasticSearch رو یه امتحان کنید.
> هم Couchbase هم ElasticSearch امکانات Clustering و Sharding خوبی در اختیارتون قرار میدن.


سلام
ممنون از پاسختون
این ElasticSearch رایگان هست ؟
میتونید کمی توضیح بدید بفرمایید دقیقا چیه ،چه کسانی ازش استفاده میکنن،دیتابیس هست یا مثل apache solr میمونه(چون قبلا با apache solr کار کردم)
درضمن سمت سرور از php استفاده میکنیم
تو این لیست هم نگاه کردم
درایور برای Couchbase بود ولی از CouchDB خبری نبود هر چند چنتا مثال از CouchDB تو اینترنت دیدم ولی چرا تو لیست درایورها نبود.(البته میشه درایورش رو دانلود کرد اما از سایتی بجز این سایت)
نظر خودتون چیه با توجه به شناخت بیشتری که نسبت به این دو دارید حقیقت یک پروژه بزرگه نمیخایم بعدها توش به راه بسته بخوریم یا برامون دردسر بوجود بیاره،البته روزه شکدارهم نمیگیریم قطعا تحقیق ویژه ای میکنیم ولی نظر شما و سایر استاد و افراد با تجربه برامون ارزشمند هست

----------


## cups_of_java

اگه به سایت الستیک سرچ سر میزدید متوجه میشدید که متن باز و رایگاه هستش و از پلاگین ها و پشتیبانی خیلی خوبی هم برخورداره....
بله دیتابیس هم هست اما خب اکثرن در کنار یک دیتایس ازش استفاده میکنن (میشه گفت بیشتر نقش Solrرو برای انیدکس کردن اطلاعات و جستجوی سریع بازی میکنه.
برای PHP من خودم قبلن درایور CouchDB استفاده کردم. توی خود سایتش پیدا میکنید.

هر جفت این دو تا بزرگ هستن. CouchDB به راحتی جواب شما رو میده فکر نمیکنم نیازی به CouchBase پیدا کنید تا چند سال اول... ضمنن خصوصیات این دو کمی با هم فرق داره و شما به هر حال یکی رو انتخاب خواهید کرد... مثلن CouchDB به شما دسترسی Http میده اما CouchBaseدرایور نیتیو میخواد... خب اینا میتونه تاثیر گذار باشه تو جنس پروژه
هر دوی این دیتابیس ها جستجوی قوی ای به شما نمیدن. در حالیکه map/reduce قدرتمندی در اختیارتون میزارن.

الستیک سرچ برای جفت این دو تا River داره که می تونید فعال کنید. و روی دیتاتون سرچ کنید.

----------


## behnamy01

الان جواب این تاپیک چی شد؟ بهترین دیتابیس noSQL برای کار جستجوی متن، استفاده از دیتابیس CouchDB یا Couchbase یا ElasticSearch  هستش؟

----------


## cups_of_java

برای Fulltext search از بین این موارد فقط ElasticSearch کمکتون میکنه. گزینه های اختصاصی دیگه هم برای این کار باید باشن البته.
ضمنن اصولن ElasticSearch روی دیتابیس ها قرار میگیره برای ایندکس کردن... به تنهایی اصولن استفاده نمیشه.

----------


## behnamy01

> برای Fulltext search از بین این موارد فقط ElasticSearch کمکتون میکنه. گزینه های اختصاصی دیگه هم برای این کار باید باشن البته.
> ضمنن اصولن ElasticSearch روی دیتابیس ها قرار میگیره برای ایندکس کردن... به تنهایی اصولن استفاده نمیشه.


خیلی ممنون از شما، من دیروز خیلی مطلب اینجا خوندم، یکی شما و یکی مدیر بخش خیلی فعالیت داشتید توی این بخش و من ازتون بابت این موضوع خیلی تشکر میکنم.

اگر اشتباه نکنم خود شما قبلا یک لینکی داده بود که رتبه بندی دیتابیس ها بود، http://db-engines.com/en/ranking

اینجا رو که دیدم متوجه شدم بین دیتابیس های NoSQL بالاترین رنک مربوط به MongoDB بود، MongoDB رو قبلا زیاد در موردش شنیده بودم و توی وب فارسی هم آموزش های زیادی در موردش دیدم که میتونم یاد بگیرم ولی بقیه دیتابیس های Nosql رو کمتر منبع آموزشی الخصوص فارسی دیدم. پیشنهاد میکنید واسه کار جستجوی متن هم همین دیتابیس رو انتخاب کنم و بیخیال بقیه دیتابیس های ناشناخته تر بشم؟ بقیه کارام رو هم که با همون MySQL نیازام رو برطرف میکنم. و نیازی نیست واسه هر کاری یک دیتابیس NoSQL یاد بگیرم و استفاده کنم!

فرض کنید من دو میلیون رکورد متن دارم که بین مثلا 5 تا 50 خط هستن. چیز دیگه ای هم ندارم اصلا! یک فیلد متن فقط! و میخوام یک جمله یا عبارت رو توی اونا جستجو کنم، میتونید به صورت *کمی* مقایسه کنید که اگر مثلا Mysql استفاده کنم مثلا 10 ثانیه زمان میبره و حتی ممکنه همه نتایج رو هم برنگردونه، و اگر مثلا از MongoDB استفاده کنم 0.5 ثانیه زمان لازمه و اگر از بهترین دیتابیس موجود برای Fulltext search استفاده کنم مثلا 0.1 ثانیه زمان میبره؟
اگر زمان ها اینجوری که من فرض کردم باشه به نظر من منطقی تره که همون MongoDB استفاده کنم و خودم رو درگیر دیتابیس های ناشناخته تر نکنم!

----------


## cups_of_java

مونگو دی بی بهتون امکان جستجوی متنی میده و خوب می تونید استفاده کنیدش اما در نهایت توی اجرا های بزرگ از Solr یا ElasticSearch استفاده میکنند.

----------


## -سیّد-

> فرض کنید من دو میلیون رکورد متن دارم که بین مثلا 5 تا 50 خط هستن. چیز دیگه ای هم ندارم اصلا! یک فیلد متن فقط! و میخوام یک جمله یا عبارت رو توی اونا جستجو کنم، میتونید به صورت *کمی* مقایسه کنید که اگر مثلا Mysql استفاده کنم مثلا 10 ثانیه زمان میبره و حتی ممکنه همه نتایج رو هم برنگردونه، و اگر مثلا از MongoDB استفاده کنم 0.5 ثانیه زمان لازمه و اگر از بهترین دیتابیس موجود برای Fulltext search استفاده کنم مثلا 0.1 ثانیه زمان میبره؟
> اگر زمان ها اینجوری که من فرض کردم باشه به نظر من منطقی تره که همون MongoDB استفاده کنم و خودم رو درگیر دیتابیس های ناشناخته تر نکنم!


ضمن تشکر از دوستمون برای جوابهای خوبشون، این رو اضافه کنم:

انتخاب یک پایگاه داده به خیلی عوامل بستگی داره. به عنوان مثال، آیا داده‌های شما read-only هستند؟ اگه نه، نرخ ورودی داده چقدر هست؟ چند درصدش از نوع به‌روزرسانی هست؟

حالا اگه فرض کنیم که داده‌های شما به‌روزرسانی ندارن، برای ۲ میلیون رکورد ۵-۵۰ خط، که مثلاً اگه هر خط رو ۱۵۰ کاراکتر فرض کنیم (البته بستگی به اندازه‌ی خطها داره!)، می‌شه مثلاً حدود 1k - 10k که می‌شه فرض کرد متوسط 5k هست.
جستجو روی ۲ میلیون رکورد 5k توی MySql نباید ۱۰ ثانیه طول بکشه! یه مقدار تخمینتون رو بالا گرفتید. من این مورد خاص رو آزمایش نکردم ولی از روی تجربه‌ای که روی صفحات وب داشتم (که از این مقداری که شما گفتید یه مقدار بزرگ‌تر هستن) به نظرم می‌رسه که روی این dataset یه query نباید بیشتر از ۱۰۰ میلی‌ثانیه طول بکشه. البته می‌تونید این رو تست کنید. یه MySql نصب کنید، یه دیتاست (مثل دامپ ویکیپدیا یا دیتاست‌های کوچکتر موجود در وب) رو دریافت کنید و روش آزمایش کنید. البته مراقب باشید که دیتایی که روش آزمایش می‌کنید، دیتای شبه واقعی باشه. اگه ۲۰۰۰ تا صفحه رو هر کدوم رو ۱۰۰۰ بار تکرار کنید، نتایجی که به دست میارید یه مقدار غیر واقعی می‌شه.

یه نکته‌ای که باید بهش دقت کنید، اینه که *اصولاً جستجوی متنی، مستقیماً ارتباطی به پایگاه داده پیدا نمی‌کنه*. توی MySql هم که می‌خواین به صورت Full Text جستجو کنید، باید اون ستون رو index کنید. جستجو روی اون index انجام می‌شه. بنابراین سرعت جستجوی متنی، به هیچ وجه ارتباطی با سرعت کارهای دیگه توی پایگاه داده نداره. یعنی اگه دریافت یه رکورد خاص از یه پایگاه داده مثلاً در ۵ میلی‌ثانیه انجام بشه، جستجوی متنی روی همون دیتا ممکنه ۵۰۰ میلی‌ثانیه طول بکشه.

در نهایت، این رو هم بگم که استفاده از FTS در پایگاه‌های داده‌ای مثل MySql، کاملاً محدود هست و قابلیت انعطاف زیادی به شما نمی‌ده (چون این پایگاه‌های داده برای این کار ساخته نشده‌اند، و این یه امکانه که روش اضافه کردن). اما در عوض استفاده از کتابخونه‌های مخصوص جستجو یا نرم‌افزارهای مخصوص جستجو (مثل ElasticSearch یا Solr یا Sphinx) به شما امکانات بیشتری برای جستجو می‌ده و قطعاً سرعت بالاتری هم در جستجو دارن.
همونطور که دوستمون گفتن، معمولاً در کنار این نرم‌افزارهای جستجو، از یه پایگاه داده برای Document Retrieval استفاده می‌کنن. یعنی شما می‌تونید مثلاً از Sphinx در کنار MySql استفاده کنید (دیگه توی MySql نیازی نیست فیلدهای متنی رو index کنید) که هم سرعت جستجوی بالایی داشته باشید، هم سرعت دریافت اطلاعات بالا. این حالتی که گفتم، برای ۲ میلیون رکورد به راحتی آب خوردن جواب می‌ده و زمان‌های جستجوی به راحتی زیر ۱۰۰ میلی‌ثانیه خواهید داشت. قدرت نرم‌افزارهای مخصوص جستجو خیلی بیشتر از این حرفهاست! برای دریافت اطلاعات هم که برای MySql تا صدها میلیون رکورد مشکلی پیش نمیاد.
البته باز بستگی به شرایط داره، نحوه‌ی استفاده، سخت‌افزار مورد استفاده (هارد دیسک - پردازنده - RAM)، نرخ به‌روزرسانی داده‌ها، طراحی جدول‌های پایگاه داده، ...

برای این که یه درک کلی از موضوع پیدا کنید، می‌تونید یه جستجوی ساده رو در موتور یوز امتحان کنید. دقت کنید که بیش از یک میلیارد صفحه توی index یوز وجود داره (البته توزیع شده هست، نه روی یک سرور). البته ما توی موتور یوز از هیچ کدوم از این تکنولوژی‌ها (ElasticSearch - Solr - Sphinx) استفاده نکردیم و index توزیع‌شده‌مون رو خودمون پیاده‌سازی کردیم. ولی بالاخره کلیات index ما و این تکنولوژی‌ها مشابه هم هستند و یه sense ای از سرعت جستجو پیدا خواهید کرد، که مثلاً اگه ۲ میلیون رکورد بیشتر نخواهید داشت، MySql هم احتمالاً جواب کارتون رو می‌ده (مگه این که بخواین برای جستجوتون الگوریتم‌های خاص استفاده کنید که توی MySql نمی‌شه تغییری توی الگوریتم جستجوش داد).

----------


## behnamy01

> توی MySql هم که می‌خواین به صورت Full Text جستجو کنید، باید اون ستون رو index کنید. جستجو روی اون index انجام می‌شه. بنابراین سرعت جستجوی متنی، به هیچ وجه ارتباطی با سرعت کارهای دیگه توی پایگاه داده نداره. یعنی اگه دریافت یه رکورد خاص از یه پایگاه داده مثلاً در ۵ میلی‌ثانیه انجام بشه، جستجوی متنی روی همون دیتا ممکنه ۵۰۰ میلی‌ثانیه طول بکشه.


ممنون دوست عزیز از پاسختون.
من اتفاقا همین دیشب یک دستور DISTINCT ساده از تنها یک فیلد جدولی در MySQL گرفتم که حدود 350 هزار رکورد داشت، زمان پاسخوگی حدود 8 ثانیه بود!! و اومدم اون فیلد رو index کردم و به زمان 0.005 ثانیه رسیدم!! که کاملا تاثیر index گذاری واسم روشن شد، ولی همون دیشب متوجه شدم که نمیشه برای فیلدهای با type برابر با text و BLOB در مای اس کیوال INDEX گذاشت که مجبور شدم TYPE اون فیلد رو به varchar تغییر بدم که میدونید محدودیت 255 کاراکتری داره، برای همین من نمیتونم این 2 میلیون رکورد text رو که گفتید رو index کنم!

----------


## -سیّد-

> من اتفاقا همین دیشب یک دستور DISTINCT ساده از تنها یک فیلد جدولی در  MySQL گرفتم که حدود 350 هزار رکورد داشت، زمان پاسخوگی حدود 8 ثانیه بود!!  و اومدم اون فیلد رو index کردم و به زمان 0.005 ثانیه رسیدم!! که کاملا  تاثیر index گذاری واسم روشن شد


دلیلش اینه که وقتی شما index ندارید، کل داده‌ها باید پردازش بشن. ولی وقتی index می‌ذارید، سیستم می‌دونه باید به سراغ کدوم بخش بره.




> ولی همون دیشب متوجه شدم که نمیشه برای فیلدهای با type برابر با text و BLOB در مای اس کیوال INDEX گذاشت که مجبور شدم TYPE اون فیلد رو به varchar تغییر بدم که میدونید محدودیت 255 کاراکتری داره، برای همین من نمیتونم این 2 میلیون رکورد text رو که گفتید رو index کنم!


حتماً یه اشتباهی کردید. طبق چیزی که توی manual نوشته، فیلد text رو به صورت full-text می‌شه  index کرد:
http://dev.mysql.com/doc/refman/5.7/...xt-search.html



> Full-text indexes can be used only with           InnoDB or           MyISAM tables, and can be created           only for CHAR,           VARCHAR, or           TEXT columns.




و البته blob رو هم می‌شه index کرد، ولی نه full-text.

----------


## behnamy01

> دلیلش اینه که وقتی شما index ندارید، کل داده‌ها باید پردازش بشن. ولی وقتی index می‌ذارید، سیستم می‌دونه باید به سراغ کدوم بخش بره.
> 
> 
> حتماً یه اشتباهی کردید. طبق چیزی که توی manual نوشته، فیلد text رو به صورت full-text می‌شه  index کرد:
> http://dev.mysql.com/doc/refman/5.7/...xt-search.html
> 
> 
> و البته blob رو هم می‌شه index کرد، ولی نه full-text.


از لحاظ ایندکس نشدن text که مطمئنم چون تست کردم و اررور میداد، جواب اول لینک زیر رو هم اگر ببینید حرف منو تایید میکنه.
http://stackoverflow.com/questions/2...ql-text-column
ولی فکر میکنم شما منظورتون از index چیز دیگه ای هستش که من بلد نیستم احتمالا.
منظورتون از index برای  full-text چیه دقیقا؟
من منظورم از index گزینه ای هستش که در عکس زیر مشخص کردم:

----------


## -سیّد-

> از لحاظ ایندکس نشدن text که مطمئنم چون تست کردم  و اررور میداد، جواب اول لینک زیر رو هم اگر ببینید حرف منو تایید میکنه.
> http://stackoverflow.com/questions/2...ql-text-column
> ولی فکر میکنم شما منظورتون از index چیز دیگه ای هستش که من بلد نیستم احتمالا.
> منظورتون از index برای  full-text چیه دقیقا؟


اگه اون جواب رو دقیق بخونید، می‌بینید که گفته:



> You can't have a UNIQUE index on a text column in MySQL.




نوع index ای که برای text استفاده می‌شه، اسمش هست full-text که با index معمولی (unique یا غیره) فرق اساسی داره.

اجازه بدید یه توضیح کلی درباره‌ی index ها بدم تا قضیه روشن بشه:
شما  وقتی روی یه ستون جدولتون از نوع int یه unique index می‌ذارین، یعنی این که می‌خواین  این ستون یکتا باشه، یعنی هیچ مقدار تکراری‌ای قبول نکنه.
پس پایگاه  داده‌ی شما، وقتی یه مقدار اضافه می‌کنید، اون رو توی یه ساختاری (مثلاً B-Tree) ذخیره  می‌کنه که بتونه تشخیص بده داده‌های جدید تکراری هستند یا نه.

اما اینجا قضیه یه کم متفاوته. وقتی نوع داده‌ی شما text هست، یعنی توش یه مشت کلمه دارید نه یه دونه عدد. بنابراین اینجا یه مقدار بی‌معنی هست که بگیم می‌خوایم به unique index روش داشته باشیم. یعنی فکر کنید یه سطر اضافه کردید که توش مقدار text مورد بحث یه متن ۱۰۰ کلمه‌ای هست. حالا اصلاً مگه ممکنه که شما یه بار دیگه عییییین همین متن رو به پایگاه داده اضافه کنید؟! درسته که ممکنه، ولی هزینه‌ی چک کردن این قضیه برای پایگاه داده فوق‌العاده بالا هست (وقتی داده‌تون int هست، فقط ۴ بایت هست، ولی اینجا با صدها و هزاران بایت سر و کار داریم).
برای همینه که حداکثر به شما اجازه می‌ده روی varchar ایندکس unique تعریف کنید.

حالا فرق این دو نوع index رو بررسی کنیم: وقتی یه داده از نوع int رو index می‌کنید، می‌خواین عین همون رو جستجو کنید (یا عملگرهایی مانند کوچکتر و بزرگتر). ولی وقتی یه متن رو index می‌کنید، می‌خواین فقط یه کلمه رو توی اون متن جستجو کنید. پس اتفاقی که می‌افته اینه که باید کل متن شما به صورت کلمه به کلمه index بشه (کل متن = full text). پس وقتی که index از نوع full text اضافه می‌کنید، پایگاه داده موقع افزودن یه سطر شروع می‌کنه به این کارا: اول متن شما رو tokenize می‌کنه تا کلماتش به صورت جدا جدا به دست بیاد. بعدش هر کلمه رو (در صورت جدید بودن) توی یه جایی به نام terms dictionary اضافه می‌کنه (یعنی به هر کلمه یه ID اختصاص می‌ده که بتونه بعداً راحت lookup اش کنه). در نهایت برای هر کلمه به صورت جداگانه ذخیره می‌کنه که توی این رکورد دیده شده.

یه مثال که یه کم قضیه روشن‌تر بشه:
فرض کنید سطر شماره‌ی ۱ رو اضافه کردید، شامل این متن:
this is a book.

خوب در اثر مرحله‌ی اول (tokenization)، این کلمات به دست میان:

thisisabook

(دقت کنید که علامت نقطه‌ی آخر متن از بین رفت.)

بعد به terms dictionary افزوده می‌شن:

this = 1is = 2a = 3book = 4


در نهایت جلوی هر کدوم از این کلمات نوشته می‌شه که توی رکورد شماره‌ی ۱ دیده شدن:
1 => 1
2 => 1
3 => 1
4 => 1
(اون عددای اول، ID کلمات هستن)

حالا سطر شماره‌ی ۲ رو اضافه می‌کنید، شامل این متن:
was this a good book?
خروجی tokenization:

wasthisagoodbook


افزودن به terms dictionary:

was = 5this ==> 1a ==> 3good = 6book ==> 4

اینجا ۳ تا کلمه‌ی تکراری داشتیم.

مرحله‌ی آخر، به‌روزرسانی فهرست رکوردهای شامل کلمه برای هر کدوم از کلمات هست:
1 => 1,2
2 => 1
3 => 1,2
4 => 1,2
5 => 2
6 => 2

خوب حالا شما جستجو می‌کنید a. اول توی terms dictionary می‌ره می‌گرده پیداش می‌کنه (می‌شه 3)، بعد می‌ره نگاه می‌کنه جلوی 3 نوشته 1,2. پس نتیجه‌ی جستجوی شما می‌شه رکورد ۱ و ۲.
حالا نوبت رتبه‌بندی می‌رسه. اول ۱ رو به شما برگردونه یا ۲ رو؟ یعنی 1,2 بده، یا 2,1 ؟
یا جستجو می‌کنید a book. اینجا سیستم می‌ره رکوردهای مشترک بین a و book رو استخراج می‌کنه و به شما برمی‌گردونه.
یا جستجو می‌کنید "a book". اینجا باید سیستم بدونه که توی کدوم سندها a و book دقیقاً پشت سر هم اومدن. پس باید جای کلمات رو هم کنار فهرست رکوردهای هر کلمه ذخیره کنه (خود این قضیه کلللللی حجم index رو زیاد می‌کنه، در حد ۲ برابر).

اینایی که گفتم کلیات روش index کردن متن در همه‌ی سیستم‌ها هست. حالا این که توی MySql دقیقاً به چه شکلی پیاده‌سازی شده، ممکنه بعضی جاها توی جزئیاتش متفاوت باشه.

اینم لینک full-text برای MySql:
http://dev.mysql.com/doc/refman/5.7/...xt-search.html

این رو هم ببینید:
http://dev.mysql.com/doc/refman/5.7/...ne-tuning.html



> MySQL's full-text search capability has few user-tunable         parameters. You can exert more control over full-text searching         behavior if you have a MySQL source distribution because some         changes require source code modifications.



یعنی مثلاً نحوه‌ی tokenization و یا نحوه‌ی رتبه‌بندی رو اگه می‌خواین دستکاری کنید، باید source ه MySql رو بردارید دستکاری کنید!

خوب بعد از این توضیحات، برای افزودن full-text به یه ستون، می‌تونید از دستور زیر استفاده کنید:
ALTER TABLE t ADD FULLTEXT (data);
http://stackoverflow.com/a/5626539

----------

