سؤال

أتساءل كيف سيكون أداء الاستعلام باستخدام الكلمة الأساسية LIKE وحرف البدل كقيمة مقارنة بعدم وجود جملة أين على الإطلاق.

فكر في جملة حيث مثل "WHERE a LIKE '%'".سيطابق هذا جميع القيم الممكنة للعمود "أ".كيف يمكن مقارنة هذا بعدم وجود جملة أين على الإطلاق.

السبب وراء طرحي هذا السؤال هو أن لدي تطبيقًا به بعض الحقول التي يمكن للمستخدم تحديد قيم للبحث عنها.في بعض الحالات، يرغب المستخدم في الحصول على جميع النتائج المحتملة.أستخدم حاليًا استعلامًا واحدًا مثل هذا:

SELECT * FROM TableName WHERE a LIKE ? AND b LIKE ?

يمكن توفير قيم '%' و'%' لمطابقة كافة القيم الممكنة لـ a و أو b.يعد هذا مناسبًا حيث يمكنني استخدام استعلام مسمى واحد في طلبي لهذا الغرض.وأتساءل ما هي اعتبارات الأداء لهذا الغرض.هل يقوم مُحسِّن الاستعلام بتقليل LIKE '%' ليطابق الكل ببساطة؟أدرك ذلك لأنني أستخدم استعلامًا مسمىًا (بيان مُجهز)، فقد يؤثر ذلك أيضًا على الإجابة.أدرك أن الإجابة من المحتمل أن تكون محددة لقاعدة البيانات.إذن كيف سيعمل هذا على وجه التحديد في Oracle وMS SQL Server وDerby.

سيكون الأسلوب البديل لذلك هو استخدام 3 استعلامات منفصلة بناءً على قيام المستخدم بإدخال حرف البدل.

A هو استعلام حرف البدل:

SELECT * FROM TableName WHERE b LIKE ?

B هو استعلام حرف البدل:

SELECT * FROM TableName WHERE a LIKE ?

A وB عبارة عن أحرف بدل:

SELECT * FROM TableName

لا توجد أحرف بدل:

SELECT * FROM TableName WHERE a LIKE ? AND b LIKE ?

من الواضح أن وجود استعلام واحد هو الأبسط والأسهل في الصيانة.أفضل استخدام استعلام واحد فقط إذا كان الأداء سيظل جيدًا.

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

المحلول 3

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

يستهدف تطبيقي بشكل أساسي قواعد بيانات Derby وMS SQL وOracle.نظرًا لأنه يمكن تشغيل Derby بشكل مضمن وسهل الإعداد، فقد قمت باختبار الأداء عليه أولاً.وكانت النتائج مفاجئة.لقد اختبرت السيناريو الأسوأ مقابل طاولة كبيرة إلى حد ما.لقد أجريت الاختبار 1000 مرة وحصلت على متوسط ​​النتائج.

الاستعلام 1:

SELECT * FROM TableName

الاستعلام 2 (بقيمتي a="%" وb="%"):

SELECT * FROM TableName WHERE a LIKE ? AND b LIKE ?

الاستعلام 1 متوسط ​​الوقت:178 مللي ثانية

الاستعلام 2 متوسط ​​الوقت:181 مللي ثانية

لذا فإن الأداء في الديربي هو نفسه تقريبًا بين الاستعلامين.

نصائح أخرى

سوف

وSQL خادم يرى عموما

WHERE City LIKE 'A%'

ووالتعامل معها على أنها

WHERE City >= 'A' AND City < 'B'

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

إذا شخص ما يحاول القيام به:

WHERE City LIKE '%ville'

... ثم مؤشر تسعى سيكون من المستحيل أساسا.

ولكن شيء بسيط مثل:

WHERE City LIKE '%'

وسينظر يعادل:

WHERE City IS NOT NULL

يمكنك استخدام أي تحليل استعلام يقدمه نظام إدارة قواعد البيانات (على سبيل المثال. EXPLAIN ل MySQL، SET SHOWPLAN_ALL ON لـ MS SQL (أو استخدم أحد أساليب أخرى), EXPLAIN PLAN FOR لـ Oracle) لمعرفة كيفية تنفيذ الاستعلام.

وأي DBMS تستحق أن الملح تجريد من بنود LIKE '%' حتى قبل محاولة تشغيل الاستعلام. أنا متأكد إلى حد ما رأيت DB2 / ض القيام بذلك في خطط تنفيذه.

ويجب على بيان معد سلفا لن يحدث فرقا لأنه يجب أن تتحول إلى <م> حقيقية SQL قبل أن يحصل على محرك التنفيذ.

ولكن، كما هو الحال مع جميع الأسئلة الأمثل، <م> التدبير، لا تخمين ! توجد دباس لأنهم باستمرار ضبط DBMS على أساس البيانات الفعلية (والذي يتغير مع مرور الوقت). في الحد الأدنى، يجب أن الوقت (والحصول على خطط التنفيذ) لجميع الاختلافات مع بيانات ثابتة مناسبة لمعرفة ما إذا كان هناك فرق.

وأنا أعلم أن الأسئلة مثل:

select c from t where ((1 = 1) or (c = ?))

و الأمثل لإزالة كامل حيث شرط قبل التنفيذ (على DB2 على أي حال، وقبل أن تسأل، وبناء مفيد حيث تحتاج إلى إزالة أثر شرط حيث ولكن لا تزال تحافظ على المعلمة نائب (باستخدام BIRT مع جافا سكريبت لتعديل استعلامات البدل)).

وديربي كما يقدم أدوات لفحص خطة الاستعلام الفعلية التي تم استخدامها، حتى تتمكن من تشغيل التجارب باستخدام دربي وإلقاء نظرة على خطة الاستعلام الذي اختار ديربي. يمكنك تشغيل ديربي مع -Dderby.language.logQueryPlan = صحيح، وسوف ديربي كتابة خطة الاستعلام إلى derby.log، أو يمكنك استخدام مرفق RUNTIMESTATISTICS، كما هو موضح هنا: <لأ href = "HTTP: //db.apache كافيه / دربي / مستندات / 10.5 / ضبط / ctundepth853133.html "يختلط =" نوفولو noreferrer "> http://db.apache.org/derby/docs/10.5/tuning/ctundepth853133.html

وأنا لست متأكدا مما اذا كان دربي سترفع من ألف LIKE '٪' في وقت مبكر، لكنني أيضا لا أعتقد أن وجود هذا الشرط سوف أعرض بكثير من حدوث تباطؤ في سرعة التنفيذ.

وسأكون مهتما جدا أن نرى إخراج خطة الاستعلام الفعلية التي تحصل في البيئة الخاصة بك، مع وبدون شرط ألف LIKE '٪' في المكان.

وأوراكل 10gR2 لا يبدو أن إجراء الأمثل خاص لهذه الحالة، ولكن لا ندرك أن LIKE '٪' تستثني بالقيم الخالية.

create table like_test (col1)
as select cast(dbms_random.string('U',10) as varchar2(10))
from dual
connect by level <= 1000
/
insert into like_test values (null)
/
commit
/

exec dbms_stats.gather_table_stats(user,'like_test')

explain plan for
select count(*)
from   like_test
/
select plan_table_output from table(dbms_xplan.display)
/
explain plan for
select count(*)
from   like_test
where  col1 like '%'
/
select plan_table_output from table(dbms_xplan.display)
/
explain plan for
select count(*)
from   like_test
where  col1 is not null
/
select plan_table_output from table(dbms_xplan.display)
/

... إعطاء ...

Plan hash value: 3733279756

------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Cost (%CPU)| Time     |
------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |           |     1 |            |          |
|   2 |   TABLE ACCESS FULL| LIKE_TEST |  1001 |     3   (0)| 00:00:01 |
------------------------------------------------------------------------

و... و ...

Plan hash value: 3733279756

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    10 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |           |     1 |    10 |            |          |
|*  2 |   TABLE ACCESS FULL| LIKE_TEST |  1000 | 10000 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("COL1" LIKE '%')

و... و ...

Plan hash value: 3733279756

--------------------------------------------------------------------------------
| Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |           |     1 |    10 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |           |     1 |    10 |            |          |
|*  2 |   TABLE ACCESS FULL| LIKE_TEST |  1000 | 10000 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("COL1" IS NOT NULL)

لاحظ أصل (صفوف) على خط كامل الجدول ACCESS

واعتمادا على كيفية المسند يعجبني هو منظم وعلى الحقل الذي نجري اختبارات على، قد تحتاج إلى تفحص الجدول الكامل. لغويا و'٪' قد ينطوي على مسح جدول كامل ولكن مزود خدمة يفعل كل أنواع الأمثل داخليا على الاستفسارات. لذلك يصبح السؤال: هل تحسين SQL Server على دالة التقييم LIKE شكلت مع '٪' ويلقي بها من جملة WHERE

أحد الجوانب التي أعتقد أنها مفقودة من المناقشة هو حقيقة أن البروتوكول الاختياري يريد استخدام بيان مُجهز.في الوقت الذي يتم فيه إعداد البيان، لن تتمكن قاعدة البيانات/المُحسِّن من تنفيذ التبسيطات التي ذكرها الآخرون وبالتالي لن تكون قادرة على التحسين بعيدًا عن a like '%' لأن القيمة الفعلية لن تكون معروفة في وقت الإعداد.

لذلك:

  • عند استخدام البيانات المعدة، يجب أن تتوفر لديك أربع عبارات مختلفة (0، فقط أ، فقط ب، كلاهما) واستخدم العبارة المناسبة عند الحاجة
  • معرفة ما إذا كنت ستحصل على أداء أفضل عندما لا تستخدم عبارة معدة عند الالتزام ببيان واحد فقط (على الرغم من أنه سيكون من السهل جدًا عدم تضمين الشروط "الفارغة")

وماذا لو كان العمود يحتوي على قيمة فارغة غير فارغة؟ وربما طلبك تطابق ذلك.

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

وبسيطة إذا بيان إذا (A B)  بحث أ ب آخر (A)  البحث في آخر B  البحث ب آخر  أقول المستعمل أنها لم تحدد أي شيء

وغير تافهة لصيانة ويصبح أسهل بكثير لفهم بدلا من وضع افتراضات حول التشغيل LIKE. ربما كنت ذاهب للقيام بذلك في واجهة المستخدم على أي حال عند عرض نتائج "بحثك عن وتبين في دراسة س" أو "وجدت بحثك عن A B ..."

ولست متأكدا من قيمة استخدام بيان معد سلفا مع هذا النوع من المعلمات كنت واصفا. والسبب هو أنك قد تخدع محسن الاستعلام إلى إعداد خطة التنفيذ التي من شأنها أن تكون خاطئة تماما اعتمادا على أي من المعلمات و'٪'.

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

وجملة WHERE مع "مثل '٪'" كما المسند الوحيد سوف تتصرف بالضبط نفس أي بند فيها على الإطلاق.

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