মাইএসকিউএল অন্য সারণীর বিপরীতে যোগদানের জন্য সূচী ব্যবহার করছে না


11

আমার দুটি টেবিল রয়েছে, প্রথম টেবিলটিতে একটি সিএমএসের মধ্যে সমস্ত নিবন্ধ / ব্লগ পোস্ট রয়েছে। এর মধ্যে কিছু নিবন্ধ একটি ম্যাগাজিনেও উপস্থিত হতে পারে, এক্ষেত্রে তাদের অন্য একটি টেবিলের সাথে বৈদেশিক কী সম্পর্ক রয়েছে যাতে ম্যাগাজিনের নির্দিষ্ট তথ্য রয়েছে।

এই দুটি টেবিলের জন্য কিছু অ-অপরিহার্য সারিগুলি ছাঁটাই করে টেবিলের সিনট্যাক্স তৈরি করার একটি সরল সংস্করণ এখানে দেওয়া হয়েছে:

CREATE TABLE `base_article` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `date_published` datetime DEFAULT NULL,
  `title` varchar(255) NOT NULL,
  `description` text,
  `content` longtext,
  `is_published` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `base_article_date_published` (`date_published`),
  KEY `base_article_is_published` (`is_published`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `mag_article` (
    `basearticle_ptr_id` int(11) NOT NULL,
    `issue_slug` varchar(8) DEFAULT NULL,
    `rubric` varchar(75) DEFAULT NULL,
    PRIMARY KEY (`basearticle_ptr_id`),
    KEY `mag_article_issue_slug` (`issue_slug`),
    CONSTRAINT `basearticle_ptr_id_refs_id` FOREIGN KEY (`basearticle_ptr_id`) REFERENCES `base_article` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

সিএমএসে মোট প্রায় 250,000 নিবন্ধ রয়েছে এবং আমি একটি সাধারণ পাইথন স্ক্রিপ্ট লিখেছি যা যদি তারা স্থানীয়ভাবে এই সমস্যাটির প্রতিলিপি তৈরি করতে চায় তবে নমুনা ডেটা সহ একটি পরীক্ষামূলক ডাটাবেস তৈরি করতে ব্যবহার করা যেতে পারে।

আমি যদি এই টেবিলগুলির মধ্যে একটি থেকে নির্বাচন করি তবে মাইএসকিউএল কোনও উপযুক্ত সূচক বাছাই বা দ্রুত নিবন্ধগুলি পুনরুদ্ধার করতে সমস্যা নেই। যাইহোক, যখন দুটি টেবিলগুলি একটি সাধারণ ক্যোয়ারিতে একসাথে যোগদান করা হয় যেমন:

SELECT * FROM `base_article` 
INNER JOIN `mag_article` ON (`mag_article`.`basearticle_ptr_id` = `base_article`.`id`)
WHERE is_published = 1
ORDER BY `base_article`.`date_published` DESC
LIMIT 30

মাইএসকিউএল একটি উপযুক্ত ক্যোয়ারী এবং পারফরম্যান্স প্লামমেটগুলি চয়ন করতে ব্যর্থ। এখানে প্রাসঙ্গিক ব্যাখ্যাটি বর্ধিত (বাস্তবায়নের সময় যার জন্য এক সেকেন্ডের বেশি হবে):

+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
| id | select_type |    table     |  type  |           possible_keys           |   key   | key_len |                  ref                   | rows  | filtered |              Extra              |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
|  1 | SIMPLE      | mag_article  | ALL    | PRIMARY                           | NULL    | NULL    | NULL                                   | 23830 | 100.00   | Using temporary; Using filesort |
|  1 | SIMPLE      | base_article | eq_ref | PRIMARY,base_article_is_published | PRIMARY | 4       | my_test.mag_article.basearticle_ptr_id |     1 | 100.00   | Using where                     |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
  • 30 সেপ্টেম্বর সম্পাদনা করুন: আমি WHEREএই ক্যোয়ারী থেকে ধারাটি সরিয়ে ফেলতে পারি , তবে EXPLAINএখনও একই দেখাচ্ছে এবং কোয়েরিটি এখনও ধীর।

একটি সম্ভাব্য সমাধান হ'ল একটি সূচককে জোর করা। FORCE INDEX (base_articel_date_published)প্রায় 1.6 মিলিসেকেন্ডে চালিত ক্যোয়ারিতে ফলাফল সহ একই ক্যোয়ারী চালানো ।

+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
| id | select_type |    table     |  type  | possible_keys |             key             | key_len |           ref           | rows | filtered  |    Extra    |
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
|  1 | SIMPLE      | base_article | index  | NULL          | base_article_date_published |       9 | NULL                    |   30 | 833396.69 | Using where |
|  1 | SIMPLE      | mag_article  | eq_ref | PRIMARY       | PRIMARY                     |       4 | my_test.base_article.id |    1 | 100.00    |             |
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+

আমি বেশিরভাগ কারণে, যদি আমি এটিকে এড়াতে পারি তবে এই ক্যোয়ারিতে জোর করে কোনও সূচক চাপিয়ে দেওয়া উচিত নয়। সবচেয়ে উল্লেখযোগ্যভাবে, এই প্রাথমিক ক্যোয়ারীটি বিভিন্ন উপায়ে ফিল্টার করা / সংশোধন করা যেতে পারে (যেমন দ্বারা ফিল্টারিং issue_slug) এর পরে base_article_date_publishedআর ব্যবহারের জন্য সেরা সূচক হতে পারে না।

কেউ কি এই প্রশ্নের জন্য কর্মক্ষমতা উন্নত করতে কৌশল পরামর্শ দিতে পারেন?


যদি কলাম "যদি_প্রকাশিত" থাকে তবে কেবল দুটি বা তিনটি মান রাখে আপনি সেই সূচি কেই base_article_is_published( is_published) কে সত্যিই ফেলে দিতে পারেন .. আমার কাছে এটি বুলিয়ান টাইপ বলে মনে হচ্ছে ..
রেমন্ড নিজল্যান্ড

উত্তরটি সম্পাদনা করেছেন
রেমন্ড নিজল্যান্ড

উত্তর:


5

এটি সম্পর্কে কী "অস্থায়ী ব্যবহার করা; ফাইলসোর্ট ব্যবহার করা" এর প্রয়োজনীয়তা অপসারণ করা উচিত কারণ ডেটা ইতিমধ্যে সঠিকভাবে রয়েছে।

সেই প্রয়োজনটি সরাতে মাইএসকিউএলটির কেন "অস্থায়ী ব্যবহার করা; ফাইলসোর্ট ব্যবহার করা" দরকার তা জানতে হবে।

প্রয়োজনীয়তা অপসারণ সম্পর্কে ব্যাখ্যার জন্য দ্বিতীয় স্ক্যালফ্রিডল দেখুন

SELECT
      *
    FROM base_article

    STRAIGHT_JOIN 
      mag_article
    ON
      (mag_article.basearticle_ptr_id = base_article.id)

    WHERE
      base_article.is_published = 1

    ORDER BY
      base_article.date_published DESC

দেখতে http://sqlfiddle.com/#!2/302710/2

বেশ ভাল কাজ করার প্রয়োজন আমারও কিছু সময় আগে দেশ / শহর টেবিলের জন্য এখানে ডেমো উদাহরণ উদাহরণ সহ ডেটা দেখুন http://sqlfiddle.com/#!2/b34870/41

আপনার সম্পাদিত আপনিও এই উত্তরটি বিশ্লেষণ করতে চাইতে পারেন যদি বেস_আর্টিক্যাল.আইস_প্রকাশিত = 1 সর্বদা 1 টি রেকর্ড ফেরত দেয় যেমন আপনার ব্যাখ্যা হিসাবে ব্যাখ্যা করা হয়েছে একটি অন্তর্ভুক্ত জয়েন বিতরণ টেবিল নীচের উত্তরের প্রশ্নের মতো আরও ভাল পারফরম্যান্স দিতে পারে

/programming/18738483/mysql-slow-query-using-filesort/18774937#18774937


জীবন রক্ষার উত্তর! আমি কেবল ব্যবহার করছিলাম JOINতবে মাইএসকিউএল সূচকটি তুলছিল না। অনেক অনেক ধন্যবাদ রেমন্ড
ম্যাক্সিমাস

4

QUERY রেফ্যাক্টর

SELECT * FROM
(SELECT * FROM base_article
WHERE is_published = 1
ORDER BY date_published LIMIT 30) A
INNER JOIN mag_article B
ON A.id = B.basearticle_ptr_id;

অথবা

SELECT B.*,C.* FROM
(SELECT id FROM base_article
WHERE is_published = 1
ORDER BY date_published LIMIT 30) A
LEFT JOIN base_article ON A.id = B.id
LEFT JOIN mag_article C ON B.id = C.basearticle_ptr_id;

আপনার সূচিগুলি পরিবর্তন করুন

ALTER TABLE base_article DROP INDEX base_article_is_published;
ALTER TABLE base_article ADD INDEX ispub_datepub_index (is_published,date_published);

একবার চেষ্টা করে দেখো !!!


রিফ্যাক্টর: কাজ করে না আমি ভয়ে থাকি, কারণ LIMIT 30এটি সাবকোয়রিতে থাকে (এই 30 টি সারিগুলিরও সমস্ত mag_articlesটেবিলে থাকবে না)। আমি যদি LIMITবাহ্যিক ক্যোয়ারিতে স্থানান্তর করি তবে পারফরম্যান্সটি আমার আসলটির মতো same সূচকগুলি সংশোধন করুন: মাইএসকিউএল সেই সূচকটি ব্যবহার করে না। সরানো হচ্ছে WHEREআমার মূল প্রশ্নের সাথে থেকে দফা একটা পরিবর্তন আনতে মনে হচ্ছে না।
জোশমেকার

দ্বিতীয় রিফ্যাক্টর পদ্ধতিটি অবিশ্বাস্যভাবে ভাল কাজ করেছে, ক্যোরির সময়টি আমার টেবিলে 8 সেকেন্ড থেকে 0.3 সেকেন্ডে নাটকীয়ভাবে হ্রাস পেয়েছে ... ধন্যবাদ স্যার !!
andreszs
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.