(bitwise) Supersets والجهاز الفرعي في MySQL
-
12-09-2019 - |
سؤال
هي الاستعلامات التالية فعالة في MYSQL:
SELECT * FROM table WHERE field & number = number;
# to find values with superset of number's bits
SELECT * FROM table WHERE field | number = number;
# to find values with subset of number's bits
... إذا تم إنشاء مؤشر للحقل؟
إذا لم يكن الأمر كذلك، هل هناك طريقة لجعلها تعمل بشكل أسرع؟
المحلول
تحديث:
انظر هذا الإدخال في مدونتي للحصول على تفاصيل الأداء:
SELECT * FROM table WHERE field & number = number
SELECT * FROM table WHERE field | number = number
يمكن أن يكون هذا المؤشر فعال بطريقتين:
- لتجنب عمليات مسح الطاولة المبكرة (نظرا لأن القيمة للمقارنة موجودة في الفهرس نفسه)
- للحد من مجموعة القيم التي تم فحصها.
لا شرط في الاستعلامات أعلاه هو sargable., ، هذا هو الفهرس لن يتم استخدامه لمسح النطاق (مع الشروط كما هي الآن).
ومع ذلك، النقطة 1
لا يزال يحمل، والفهرس يمكن أن يكون مفيدا.
إذا كان الجدول الخاص بك يحتوي، قل، 100
بايت كل صف في المتوسط، و 1,000,000
سجلات، ثم سيحتاج مسح الطاولة إلى المسح الضوئي 100 Mb
البيانات.
إذا كان لديك فهرس (مع 4
- مفتاح، 6
Bebyte صف مؤشر وبعض النفقات العامة الداخلية)، سيحتاج الاستعلام إلى المسح الضوئي فقط 10 Mb
البيانات بالإضافة إلى بيانات إضافية من الجدول إذا نجح المرشح.
- الفحص الجدول هو أكثر كفاءة إذا كانت حالتك ليست انتقائية (لديك احتجاجات عالية لتتناسب مع الشرط).
- يعد مسح الفهرس أكثر كفاءة إذا كانت حالتك انتقائية (لديك مسابقات منخفضة لتتناسب مع الحالة).
ستتطلب كل من هذه الاستفسارات مسح الفهرس بأكمله.
ولكن عن طريق إعادة كتابة AND
استعلام يمكنك الاستفادة من تتراوح في الفهرس أيضا.
هذا الشرط:
field & number = number
يمكن فقط مطابقة الحقول إذا كانت أعلى بت من number
تم تعيين مجموعة في field
جدا.
ويجب عليك فقط تقديم هذا الشرط الإضافي للاستعلام:
SELECT *
FROM table
WHERE field & number = number
AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)
سيستخدم هذا النطاق للتصفية الخشنة وحالة الترشيح الدقيق.
المزيد من البتات ل number
هي غير مؤلفة في النهاية، كلما كان ذلك أفضل.
نصائح أخرى
أشك في أن المحسن سيؤدي إلى الرقم ...
ربما يمكنك الاتصال بشرح على هذه الاستعلامات وتأكيد تخمين التشاؤم الخاص بي. (تذكر بالطبع أن الكثير من قرارات خطة الاستعلام تستند إلى مثيل معين لقاعدة بيانات معينة، أي كميات متغيرة من البيانات و / خام مجرد بيانات مع ملف تعريف إحصائي مختلف قد تنتج خططا مميزة).
على افتراض أن الجدول لديه كمية كبيرة من الصفوف، وأن المعايير "bitwised" تظل انتقائية بما فيه الكفاية) يتحقق التحسين المحتمل عند تجنب عملية bitwise على كل صف واحد، عن طريق إعادة كتابة الاستعلام مع بناء (أو مع انضمام في
شيء من هذا القبيل (المفاهيمي، أي لم يتم اختباره)
CREATE TEMPORARY TABLE tblFieldValues
(Field INT);
INSERT INTO tblFieldValues
SELECT DISTINCT Field
FROM table;
-- SELECT * FROM table WHERE field | number = number;
-- now becomes
SELECT *
FROM table t
WHERE field IN
(SELECT Field
FROM tblFieldValues
WHERE field | number = number);
الفوائد الكاملة لنهج مثل هذه الحاجة إلى تقييم حالات الاستخدام المختلفة (كل منها مع عدد كبير من الصفوف في الجدول، نظرا لإخلاء "المكان المباشر" حيث الرقم = الرقم = الرقم "فعال بما فيه الكفاءة)، لكنني أظن هذا قد يكون أسرع بكثير. يمكن تحقيق مزيد من المكاسب إذا لم يتعين إعادة إنشاء "TBLFieldvalues" في كل مرة. إن إنشاء فعال لهذا الجدول بالطبع يعني فهرس في الحقل في الجدول الأصلي.
لقد جربت هذا بنفسي، وعمليات Bitwise ليست كافية لمنع MySQL من استخدام فهرس على عمود "الحقل". من المحتمل أن يكون هذا الفحص الكامل للمؤشر يحدث.