ماذا تفعل عندما يكون هناك تطبيق مصدر مغلق لا يصل إلى قاعدة البيانات بالطريقة المثلى؟ كيفية ضبط الاستعلامات دون تغيير التطبيق ، وربما قاعدة البيانات نفسها؟
إذا لم تكن قد طرحت مثل هذه الأسئلة ، فأنت DBA ناجحة للغاية وصارمة.
حسنًا ، إذا سُئل ، دعني أشارك المعاناة والخبرة.
تحتاج إلى تخزين المزيد من البيانات ، أو تحديد مهمة
يمكنك التمرير بأمان عبر هذا القسم إذا كان تاريخ المشكلة غير مثير للاهتمام.
في البداية ، كان لدينا نظام ملكية قام بتحليل بياناته من تنسيق مغلق إلى قاعدة بيانات PostgreSQL ، حيث نقرأ ونحلل ونعالج هذه البيانات.
بالإضافة إلى ذلك ، تستخدم أدوات هذا النظام أيضًا هذه القاعدة في عمليات معينة ، لذا فإن التخلي عنها وإنشاء نسخة بهيكلها فكرة غير مجدية.
بشكل افتراضي ، يقوم النظام تلقائيًا بحذف السجلات التي مضى عليها أكثر من أسبوع ، لذلك لم تحدث مشكلات في الأداء في المنصة.
ومع ذلك ، نحتاج إلى تخزين البيانات لفترة أطول ، طالما توجد مساحة كافية على قرص الخادم. حسنًا ، من المستحسن ألا تفقد الوصول إلى هذه البيانات ولا تزال تستخدم الأدوات المدمجة في النظام ، حتى بالنسبة للبيانات القديمة.
لذلك ، كان القرار الواضح هو جعل التقسيم والمشغلات على عمليات INSERT. التركيز بسيط للغاية وفعال. يتم إدراج البيانات في الأقسام اللازمة ، يتم تعطيل حذف السجلات القديمة ، ويبدو أن كل شيء على ما يرام.
حتى مرور عامين ولم تتراكم البيانات بشكل جيد.
هنا ، "فجأة" اتضح أن الطلبات التي قدمتها أدوات النظام المستخدم لا تحد من التحديد حسب التاريخ (أو بالأحرى ، لا تقتصر على الحقل الذي تم بناء عليه القسم). أي إذا كنا نبحث عن شيء ما - يستمر البحث في جميع الأقسام. بدأت عمليات التحديث أيضًا في التباطؤ - في ظروف لم يكن هناك سوى ID-shnik المستخدم.
نتيجة لذلك ، يتم تنفيذ الطلب لفترة طويلة ، ويسحب جميع الطلبات الأخرى ، ويزداد الحمل بسرعة.
بالطبع ، أول ما يتبادر إلى الذهن هو الاتصال بالمطور.
ومع ذلك ، فإنه في معظم الحالات لم يعد إما في منطقة الوصول ، أو سيطلب تكلفة نظام آخر من هذا القبيل لإكماله في عدة خطوط.
لذلك ، طرحت الفكرة أنه ربما يوجد بالفعل نوع من البروكسي يمكن أن يساعدنا.
نحن بحاجة إلى وكيل
لم يعثر Google السريع على إجابة واضحة على سؤال حول كيفية إعادة كتابة استعلام وارد على جانب PostgreSQL أو بعض برامج الجهات الخارجية.
لذلك (حسنًا ، فقط للمتعة أيضًا ، بالطبع) ، تمت كتابة برنامج بسيط إلى حد ما يقبل الاتصالات من العملاء ويقوم بوكلائهم في PostgreSQL. في نفس الوقت ، تتم قراءة استعلامات SQL الواردة ، ويتم استبدالها إذا لزم الأمر.
مشاركة رابط إلى جيثببينما لم أقدم أي حزم ثنائية ، لم تصل يدي. لكن التجمع بسيط جدا. كل شيء مكتوب في C ++ / كيو تي ، ل لقد كتبت على هذا لفترة طويلة ...
التكوين بسيط جدا:
حدد أي واجهة ومنفذ للاستماع إلى:
listen_address=0.0.0.0 listen_port=5433
نفرض إهمال البرنامج على الاتصال بالعنوان المحدد بدلاً من الاتصال مباشرةً بخادم PostgreSQL.
نكتب إلى أين نعيد توجيه الاتصالات (في هذا المثال ، يوجد الوكيل على نفس جهاز خادم PostgreSQL):
dst_address=127.0.0.1 dst_port=5432
وضعنا تعبيرًا عاديًا للقبول بالطلب المطلوب:
query = SELECT \* FROM tablename WHERE (.+)
نقول أننا بحاجة إلى إعادة كتابته:
action = rewrite
نقول كيفية إعادة كتابة:
rewrite = SELECT * FROM tablename WHERE (col3 >= '$(now-1M)') AND $(1)
في هذا المثال ، نضيف عامل تصفية لشروط الاستعلام حسب العمود مع التاريخ ، مع الإشارة إلى أننا مهتمون فقط بالسجلات في الشهر الماضي.
يمكن للمرء أن يكتب مثل هذا:
rewrite = SELECT * FROM tablename WHERE (col3 >= now() - interval '1 month') AND $(1)
ولكن بعد ذلك ، لن يكون الطلب هو الأمثل نظرًا لوجود الدالة now () - سيظل البحث في جميع الأقسام. للبحث فقط بما يلزم ، يجب عليك تحديد قيمة ثابتة. لذلك ، يستبدل وكيلنا الطابع الزمني بنوبة شهر واحد بدلاً من بنية $ (now-1M).
النتيجة (من السجل):
ORIGINAL query: SELECT * FROM tablename WHERE id=1; MODIFIED query (rule 1): SELECT * FROM tablename WHERE (col3 >= '2018-11-12 11:25:23.0+00') AND id=1;
وبالتالي ، يمكن استبدال أي طلب ، من حيث المبدأ. لا يتم تغيير الردود من الخادم ويتم إرسالها إلى العميل كما هي. بهذه الطريقة ، يتم تقليل تأخير الإرسال. بالإضافة إلى ذلك ، ينتظر التطبيق عادةً استجابة من تنسيق معين ، لذلك من غير المرغوب فيه تغيير مجموعة الأعمدة في الطلب والاستجابة.
من الممكن أيضًا طباعة جميع الطلبات التي تهم السجل بسهولة:
query = .+ action = log
يحتوي المستودع على تكوين به أمثلة ووصف أكثر تفصيلاً.
بالمناسبة ، من السهل تحديد مدى كتابة المطور للعمل بشكل صحيح مع قاعدة البيانات. على سبيل المثال ، إذا رأيت مثل هذا الطلب الذي يتم تنفيذه بشكل متكرر ، فقد حان الوقت لشخص يدخن الأدلة.
INSERT INTO tablename (col1, col2, col3) VALUES('value1', 1, '2018-12-31')
يجب أن يكون مثل هذا:
INSERT INTO tablename (col1, col2, col3) VALUES($1::varchar, $2::integer, $3::date)
لسوء الحظ ، حتى الآن وكيلنا غير قادر على الكتابة بهذه الطريقة: / لكن هذا ليس بالأمر الصعب. ربما في المستقبل سيكون من الممكن مع ذلك لإعادة كتابة الطلب الأول إلى الثاني.
نعم ، النقطة المهمة هي أن طبقة المقابس الآمنة (SSL) غير مدعومة حتى الآن ، وبالتالي فإن جميع الاتصالات من العملاء إلى الوكلاء ستكون بدون تشفير.
سأكون سعيدًا بالتعليقات والتعليقات.
إذا كان هناك اهتمام نشط من المستخدمين ، فربما سأواصل تطوير المشروع.
يمكنك إضافة العمل مع قواعد البيانات الأخرى.