বড় টেবিলের উপর বাম জোনের সাথে কীভাবে খুব ধীর SELECT অপ্টিমাইজ করা যায়


15

আমি গুগল করছি, স্ব-শিক্ষিত ছিলাম এবং কয়েক ঘন্টা সমাধান খুঁজছিলাম তবে কোনও ভাগ্য নেই with আমি এখানে কয়েকটি অনুরূপ প্রশ্ন পেয়েছি তবে এই ক্ষেত্রে নয়।

আমার টেবিলগুলি:

  • ব্যক্তিরা (10M সারি)
  • বৈশিষ্ট্য (অবস্থান, বয়স, ...)
  • ব্যক্তি এবং গুণাবলী ((40M সারি) এর মধ্যে লিঙ্কগুলি (এম: এম)

সম্পূর্ণ ডাম্প ~ 280MB

পরিস্থিতি: আমি person_idকয়েকটি লোকেশন ( ) থেকে কিছু ব্যক্তি ( ) হয়ে কিছু বছর ধরে জন্মগ্রহণকারী ( ) হয়ে কিছু লোকের location.attribute_value BETWEEN 3000 AND 7000( gender.attribute_value = 1) জন্মগ্রহণকারী bornyear.attribute_value BETWEEN 1980 AND 2000এবং কিছু চোখের বর্ণ ( eyecolor.attribute_value IN (2,3)) ধারণ করে সমস্ত ব্যক্তির আইডিকে বেছে নেওয়ার চেষ্টা করি ।

এটি আমার কোয়েরি ডাইনি 3 ~ 4 মিনিট। এবং আমি অনুকূলিত করতে চাই:

SELECT person_id
FROM person
    LEFT JOIN attribute location ON location.attribute_type_id = 1 AND location.person_id = person.person_id
    LEFT JOIN attribute gender ON gender.attribute_type_id = 2 AND gender.person_id = person.person_id
    LEFT JOIN attribute bornyear ON bornyear.attribute_type_id = 3 AND bornyear.person_id = person.person_id
    LEFT JOIN attribute eyecolor ON eyecolor.attribute_type_id = 4 AND eyecolor.person_id = person.person_id
WHERE 1
    AND location.attribute_value BETWEEN 3000 AND 7000
    AND gender.attribute_value = 1
    AND bornyear.attribute_value BETWEEN 1980 AND 2000
    AND eyecolor.attribute_value IN (2,3)
LIMIT 100000;

ফলাফল:

+-----------+
| person_id |
+-----------+
|       233 |
|       605 |
|       ... |
|   8702599 |
|   8703617 |
+-----------+
100000 rows in set (3 min 42.77 sec)

বর্ধিত ব্যাখ্যা:

+----+-------------+----------+--------+---------------------------------------------+-----------------+---------+--------------------------+---------+----------+--------------------------+
| id | select_type | table    | type   | possible_keys                               | key             | key_len | ref                      | rows    | filtered | Extra                    |
+----+-------------+----------+--------+---------------------------------------------+-----------------+---------+--------------------------+---------+----------+--------------------------+
|  1 | SIMPLE      | bornyear | range  | attribute_type_id,attribute_value,person_id | attribute_value | 5       | NULL                     | 1265229 |   100.00 | Using where              |
|  1 | SIMPLE      | location | ref    | attribute_type_id,attribute_value,person_id | person_id       | 5       | test1.bornyear.person_id |       4 |   100.00 | Using where              |
|  1 | SIMPLE      | eyecolor | ref    | attribute_type_id,attribute_value,person_id | person_id       | 5       | test1.bornyear.person_id |       4 |   100.00 | Using where              |
|  1 | SIMPLE      | gender   | ref    | attribute_type_id,attribute_value,person_id | person_id       | 5       | test1.eyecolor.person_id |       4 |   100.00 | Using where              |
|  1 | SIMPLE      | person   | eq_ref | PRIMARY                                     | PRIMARY         | 4       | test1.location.person_id |       1 |   100.00 | Using where; Using index |
+----+-------------+----------+--------+---------------------------------------------+-----------------+---------+--------------------------+---------+----------+--------------------------+
5 rows in set, 1 warning (0.02 sec)

প্রোফাইলিং:

+------------------------------+-----------+
| Status                       | Duration  |
+------------------------------+-----------+
| Sending data                 |  3.069452 |
| Waiting for query cache lock |  0.000017 |
| Sending data                 |  2.968915 |
| Waiting for query cache lock |  0.000019 |
| Sending data                 |  3.042468 |
| Waiting for query cache lock |  0.000043 |
| Sending data                 |  3.264984 |
| Waiting for query cache lock |  0.000017 |
| Sending data                 |  2.823919 |
| Waiting for query cache lock |  0.000038 |
| Sending data                 |  2.863903 |
| Waiting for query cache lock |  0.000014 |
| Sending data                 |  2.971079 |
| Waiting for query cache lock |  0.000020 |
| Sending data                 |  3.053197 |
| Waiting for query cache lock |  0.000087 |
| Sending data                 |  3.099053 |
| Waiting for query cache lock |  0.000035 |
| Sending data                 |  3.064186 |
| Waiting for query cache lock |  0.000017 |
| Sending data                 |  2.939404 |
| Waiting for query cache lock |  0.000018 |
| Sending data                 |  3.440288 |
| Waiting for query cache lock |  0.000086 |
| Sending data                 |  3.115798 |
| Waiting for query cache lock |  0.000068 |
| Sending data                 |  3.075427 |
| Waiting for query cache lock |  0.000072 |
| Sending data                 |  3.658319 |
| Waiting for query cache lock |  0.000061 |
| Sending data                 |  3.335427 |
| Waiting for query cache lock |  0.000049 |
| Sending data                 |  3.319430 |
| Waiting for query cache lock |  0.000061 |
| Sending data                 |  3.496563 |
| Waiting for query cache lock |  0.000029 |
| Sending data                 |  3.017041 |
| Waiting for query cache lock |  0.000032 |
| Sending data                 |  3.132841 |
| Waiting for query cache lock |  0.000050 |
| Sending data                 |  2.901310 |
| Waiting for query cache lock |  0.000016 |
| Sending data                 |  3.107269 |
| Waiting for query cache lock |  0.000062 |
| Sending data                 |  2.937373 |
| Waiting for query cache lock |  0.000016 |
| Sending data                 |  3.097082 |
| Waiting for query cache lock |  0.000261 |
| Sending data                 |  3.026108 |
| Waiting for query cache lock |  0.000026 |
| Sending data                 |  3.089760 |
| Waiting for query cache lock |  0.000041 |
| Sending data                 |  3.012763 |
| Waiting for query cache lock |  0.000021 |
| Sending data                 |  3.069694 |
| Waiting for query cache lock |  0.000046 |
| Sending data                 |  3.591908 |
| Waiting for query cache lock |  0.000060 |
| Sending data                 |  3.526693 |
| Waiting for query cache lock |  0.000076 |
| Sending data                 |  3.772659 |
| Waiting for query cache lock |  0.000069 |
| Sending data                 |  3.346089 |
| Waiting for query cache lock |  0.000245 |
| Sending data                 |  3.300460 |
| Waiting for query cache lock |  0.000019 |
| Sending data                 |  3.135361 |
| Waiting for query cache lock |  0.000021 |
| Sending data                 |  2.909447 |
| Waiting for query cache lock |  0.000039 |
| Sending data                 |  3.337561 |
| Waiting for query cache lock |  0.000140 |
| Sending data                 |  3.138180 |
| Waiting for query cache lock |  0.000090 |
| Sending data                 |  3.060687 |
| Waiting for query cache lock |  0.000085 |
| Sending data                 |  2.938677 |
| Waiting for query cache lock |  0.000041 |
| Sending data                 |  2.977974 |
| Waiting for query cache lock |  0.000872 |
| Sending data                 |  2.918640 |
| Waiting for query cache lock |  0.000036 |
| Sending data                 |  2.975842 |
| Waiting for query cache lock |  0.000051 |
| Sending data                 |  2.918988 |
| Waiting for query cache lock |  0.000021 |
| Sending data                 |  2.943810 |
| Waiting for query cache lock |  0.000061 |
| Sending data                 |  3.330211 |
| Waiting for query cache lock |  0.000025 |
| Sending data                 |  3.411236 |
| Waiting for query cache lock |  0.000023 |
| Sending data                 | 23.339035 |
| end                          |  0.000807 |
| query end                    |  0.000023 |
| closing tables               |  0.000325 |
| freeing items                |  0.001217 |
| logging slow query           |  0.000007 |
| logging slow query           |  0.000011 |
| cleaning up                  |  0.000104 |
+------------------------------+-----------+
100 rows in set (0.00 sec)

টেবিল কাঠামো:

CREATE TABLE `attribute` (
  `attribute_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `attribute_type_id` int(11) unsigned DEFAULT NULL,
  `attribute_value` int(6) DEFAULT NULL,
  `person_id` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`attribute_id`),
  KEY `attribute_type_id` (`attribute_type_id`),
  KEY `attribute_value` (`attribute_value`),
  KEY `person_id` (`person_id`)
) ENGINE=MyISAM AUTO_INCREMENT=40000001 DEFAULT CHARSET=utf8;

CREATE TABLE `person` (
  `person_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `person_name` text CHARACTER SET latin1,
  PRIMARY KEY (`person_id`)
) ENGINE=MyISAM AUTO_INCREMENT=20000001 DEFAULT CHARSET=utf8;

এসএসডি এবং 1 জিবি র‌্যাম সহ ডিজিটাল ওশান ভার্চুয়াল সার্ভারে ক্যোয়ারী করা হয়েছিল।

আমি ধরে নিয়েছি ডাটাবেস ডিজাইনে সমস্যা হতে পারে। এই পরিস্থিতিটি আরও ভালভাবে ডিজাইন করার জন্য আপনার কোনও পরামর্শ আছে? বা শুধু উপরের নির্বাচন সামঞ্জস্য করতে?


4
আপনি ইএভি ডিজাইনের জন্য এই মূল্যটি প্রদান করেন। আপনি একটি মিশ্র সূচক চেষ্টা করতে চাইতে পারেনattribute (person_id, attribute_type_id, attribute_value)
mustaccio

1
আমি এই (attribute_type_id, attribute_value, person_id)(attribute_type_id, person_id, attribute_value)
সূচিগুলি

5
এবং ইনোডিবি ব্যবহার করুন, মাইআইএসএএম ফেলে দিন। এটি 2015, মাইস্যাম দীর্ঘ মৃত।
ypercubeᵀᴹ

2
প্রথম জিনিস - বাম যোগদান থেকে পরিত্রাণ পান, আপনি আপনার সার্বিক অবস্থার সমস্ত টেবিল ব্যবহার করার ফলে এর কোনও প্রভাব নেই, কার্যকরভাবে সমস্ত সংযুক্তিকে INNER যোগদানের দিকে পরিণত করে (অপ্টিমাইজারটি বুঝতে সক্ষম হতে পারে এবং এটি অপ্টিমাইজ করতে সক্ষম হবে তবে আরও শক্ত করে না আরও ভাল) )। দ্বিতীয় জিনিস - ক্যোয়ারী ক্যাশেটি অক্ষম করুন যদি না আপনি এটির ব্যবহারের
দৃ strong়

2
ওটি: আপনি লিমিটেড আউটআর্ডার অর্ডার ব্যবহার করে কি অবাক হচ্ছেন না? এটি কিছু এলোমেলো 100000 সারি ফিরে আসবে?
ibre5041

উত্তর:


8

অন্তর্ভুক্ত করতে কয়েকটি বৈশিষ্ট্য বাছুন person। কয়েকটি সংমিশ্রণে সেগুলি সূচক করুন - একক-কলাম সূচি নয়, সম্মিলিত সূচী ব্যবহার করুন।

এটি মূলত EAV-sucks-at- পারফরম্যান্সের একমাত্র উপায়, আপনি যেখানে আছেন।

এখানে আরও আলোচনা করা হয়েছে: http://mysql.rjweb.org/doc.php/eav কী-মান সারণির পরিবর্তে জেএসএন ব্যবহার করার পরামর্শ সহ।


3

এর attributeজন্য অশ্লীলতা যুক্ত করুন :

  • (person_id, attribute_type_id, attribute_value) এবং
  • (attribute_type_id, attribute_value, person_id)

ব্যাখ্যা

আপনার বর্তমান ডিজাইনের সাহায্যে EXPLAINআপনার ক্যোয়ারী 1,265,229 * 4 * 4 * 4 = 80,974,656সারিগুলি পরীক্ষা করে দেখবে attribute। আপনি একটি যোগ করে এই সংখ্যা কমে যায় যৌগিক সূচক উপর attributeজন্য (person_id, attribute_type_id)। এই সূচক ব্যবহার করলে আপনার প্রশ্নের সাথে শুধুমাত্র প্রত্যেকের জন্য 1 4 পরিবর্তে সারি পরীক্ষা করব location, eyecolorএবং gender

আপনি যে সূচক প্রসারিত অন্তর্ভুক্ত করা হতে পারে attribute_type_valueহিসাবে ভাল: (person_id, attribute_type_id, attribute_value)। এটি এই ক্যোয়ারির জন্য এই সূচকটিকে একটি প্রচ্ছদ সূচকে রূপান্তরিত করবে , যা পারফরম্যান্সকেও উন্নত করবে।

তদ্ব্যতীত (attribute_type_id, attribute_value, person_id)(আবার অন্তর্ভুক্ত করে একটি কভারিং সূচক person_id) এর উপরে একটি সূচক যুক্ত করা attribute_valueযেখানে আরও সারি পরীক্ষা করতে হবে সেখানে কেবল এমন একটি সূচক ব্যবহার করে কর্মক্ষমতা উন্নত করা উচিত । এই ক্ষেত্রে এটি আপনার ব্যাখ্যার প্রথম ধাপটি দৃ fas় করবে: এর থেকে একটি ব্যাপ্তি নির্বাচন করা bornyear

এই দু'টি অশ্লীল ব্যবহার করে আমার সিস্টেমে আপনার ক্যোয়ারের সম্পাদনের সময়টিকে like 2.0 s থেকে কমিয়ে 0.2 ডলারে কমিয়ে ব্যাখ্যা ব্যাখ্যা করে আউটপুটটি দেখিয়েছে:

+----+-------------+----------+--------+-------------------------------------+-------------------+---------+--------------------------------+---------+----------+--------------------------+
| id | select_type | table    | type   | possible_keys                       | key               | key_len | ref                            |    rows | filtered | Extra                    |
+----+-------------+----------+--------+-------------------------------------+-------------------+---------+--------------------------------+---------+----------+--------------------------+
|  1 | SIMPLE      | bornyear | range  | person_type_value,type_value_person | type_value_person |       9 |                                | 1861881 |   100.00 | Using where; Using index |
|  1 | SIMPLE      | location | ref    | person_type_value,type_value_person | person_type_value |       8 | bornyear.person_id,const       |       1 |   100.00 | Using where; Using index |
|  1 | SIMPLE      | eyecolor | ref    | person_type_value,type_value_person | person_type_value |       8 | bornyear.person_id,const       |       1 |   100.00 | Using where; Using index |
|  1 | SIMPLE      | gender   | ref    | person_type_value,type_value_person | person_type_value |      13 | bornyear.person_id,const,const |       1 |   100.00 | Using index              |
|  1 | SIMPLE      | person   | eq_ref | PRIMARY                             | PRIMARY           |       4 | bornyear.person_id             |       1 |   100.00 | Using index              |
+----+-------------+----------+--------+-------------------------------------+-------------------+---------+--------------------------------+---------+----------+--------------------------+

1
বিস্তৃত উত্তর এবং ব্যাখ্যার জন্য ধন্যবাদ। আপনি উল্লিখিত সমস্ত কিছুই করেছি তবে ক্যোয়ারীতে এখনও 2 মিনিট সময় লাগে। দয়া করে আপনি কোন টেবিলের ধরণটি (ইনোডাব্ব, মাইসাম) ব্যবহার করছেন এবং কোন সঠিক কোয়েরি সম্পাদন করেছেন?
মার্টিন

1
অশ্লীলতা যুক্ত করা ছাড়াও আমি ঠিক একই তথ্য এবং সংজ্ঞাগুলি ব্যবহার করেছি, তাই আমি মাইআইএসএএম ব্যবহার করেছি। আমি আপনার ক্যোয়ারীর প্রথম লাইনটি এতে পরিবর্তন করেছি SELECT person.person_idকারণ অন্যথায় এটি চলবে না, সম্ভবত। ANALYZE TABLE attributeঅশ্লীলতা যোগ করার পরে আপনি কি করেছিলেন? আপনি নিজের প্রশ্নের সাথে আপনার নতুন EXPLAINআউটপুট (অশ্লীলতা যুক্ত করার পরে) যুক্ত করতেও পারেন।
ওল্ফগ্যাংওয়াল্থার

3

আমি ধরে নিয়েছি ডাটাবেস ডিজাইনে সমস্যা হতে পারে।

আপনি তথাকথিত অ্যান্টি-অ্যাট্রিবিউট-মান ডিজাইন ব্যবহার করছেন, যা প্রায়শই নকশার দ্বারা খুব ভাল, ভাল করে।

এই পরিস্থিতিটি আরও ভালভাবে ডিজাইন করার জন্য আপনার কোনও পরামর্শ আছে?

এটি নকশা করার ক্লাসিক সম্পর্কিত উপায়টি প্রতিটি বৈশিষ্ট্যের জন্য পৃথক টেবিল তৈরি করবে। সাধারণভাবে, এইসব আলাদা টেবিল হতে পারে location, gender, bornyear, eyecolor

নির্দিষ্ট বৈশিষ্ট্যগুলি সর্বদা একজন ব্যক্তির জন্য সংজ্ঞায়িত করা হয় কিনা তার উপরে নিম্নলিখিতটি নির্ভর করে। এবং, কোনও ব্যক্তির একটি গুনের একটি মাত্র মান থাকতে পারে কিনা। উদাহরণস্বরূপ, সাধারণত ব্যক্তিটির একটি মাত্র লিঙ্গ থাকে। আপনার বর্তমান ডিজাইনে কোনও কিছুতেই আপনাকে লিঙ্গের জন্য বিভিন্ন মান সহ একই ব্যক্তির জন্য তিনটি সারি যুক্ত হতে বাধা দেয় না। আপনি লিঙ্গ মান 1 বা 2 তেও সেট করতে পারবেন না, তবে 987 এর মতো এমন কিছু সংখ্যারও অর্থ নয় যা ডেটাবেসে কোনও বাধা নেই যা এটি প্রতিরোধ করবে। তবে, এটি EAV ডিজাইনের সাথে ডেটা অখণ্ডতা বজায় রাখার আরেকটি পৃথক সমস্যা।

যদি আপনি সর্বদা ব্যক্তির লিঙ্গটি জানেন তবে এটি আলাদা টেবিলে রাখলে কিছুটা বুদ্ধি হয় না এবং সারণীতে একটি নন-নাল কলাম GenderIDথাকা ভাল person, এটি তালিকার সাথে তালিকার টেবিলে একটি বিদেশী কী হবে be সমস্ত সম্ভাব্য লিঙ্গ এবং তাদের নাম। আপনি যদি ব্যক্তির লিঙ্গ বেশিরভাগ সময় জানেন তবে সর্বদা না, আপনি এই কলামটি নালাগুলি তৈরি করতে পারেন এবং NULLযখন তথ্য উপলব্ধ না হয় তখন সেট করতে পারেন । যদি বেশিরভাগ সময় ব্যক্তির লিঙ্গ পরিচিত না হয় তবে 1: 1 এর genderসাথে লিঙ্কযুক্ত আলাদা টেবিল থাকা ভাল এবং কেবলমাত্র সেই লিখিত personব্যক্তিদের জন্য সারি রয়েছে।

অনুরূপ বিবেচনাগুলি প্রযোজ্য eyecolorএবং bornyear- ব্যক্তির একটি eyecolorবা এর জন্য দুটি মান হওয়ার সম্ভাবনা কম bornyear

যদি কোনও ব্যক্তির পক্ষে কোনও গুণাবলীর জন্য কয়েকটি মান থাকা সম্ভব হয় তবে আপনি অবশ্যই এটি আলাদা টেবিলে রেখে দিতেন। উদাহরণস্বরূপ, কোনও ব্যক্তির বেশ কয়েকটি ঠিকানা (বাড়ি, কাজ, ডাক, ছুটির দিন ইত্যাদি) থাকা অস্বাভাবিক নয়, সুতরাং আপনি সেগুলি একটি টেবিলে তালিকাভুক্ত করবেন location। টেবিলগুলি personএবং locationসংযুক্ত হবে 1: এম।


বা শুধু উপরের নির্বাচন সামঞ্জস্য করতে?

যদি EAV ডিজাইন ব্যবহার করে থাকেন তবে আমি কমপক্ষে নিম্নলিখিতটি করতাম।

  • সেট কলাম attribute_type_id, attribute_value, person_idকরতে NOT NULL
  • বিদেশী কী সেট আপ করুন যা এর সাথে লিঙ্ক attribute.person_idকরে person.person_id
  • তিনটি কলামে একটি সূচক তৈরি করুন (attribute_type_id, attribute_value, person_id)। কলামগুলির ক্রম এখানে গুরুত্বপূর্ণ।
  • যতদূর আমি জানি, মাইআইএসএএম বিদেশী কীগুলি সম্মান করে না, সুতরাং এটি ব্যবহার করবেন না, পরিবর্তে ইনোডিবি ব্যবহার করুন।

আমি কোয়েরিটি এইভাবে লিখতাম। যোগদানের INNERপরিবর্তে ব্যবহার করুন LEFTএবং স্পষ্টভাবে প্রতিটি বৈশিষ্ট্যের জন্য সূচকটি লিখুন অপ্টিমাইজারকে সূচকটি ব্যবহার করার সমস্ত সুযোগ দেয়।

SELECT person.person_id
FROM
    person
    INNER JOIN
    (
        SELECT attribute.person_id
        FROM attribute
        WHERE attribute_type_id = 1
            AND location.attribute_value BETWEEN 3000 AND 7000
    ) AS location ON location.person_id = person.person_id
    INNER JOIN
    (
        SELECT attribute.person_id
        FROM attribute
        WHERE attribute_type_id = 2
            AND location.attribute_value = 1
    ) AS gender ON gender.person_id = person.person_id
    INNER JOIN
    (
        SELECT attribute.person_id
        FROM attribute
        WHERE attribute_type_id = 3
            AND location.attribute_value BETWEEN 1980 AND 2000
    ) AS bornyear ON bornyear.person_id = person.person_id
    INNER JOIN
    (
        SELECT attribute.person_id
        FROM attribute
        WHERE attribute_type_id = 4
            AND location.attribute_value IN (2, 3)
    ) AS eyecolor ON eyecolor.person_id = person.person_id
LIMIT 100000;

এছাড়াও, এটি দ্বারা টেবিলটি বিভাজনের পক্ষে মূল্যবান হতে পারে ।attributeattribute_type_id


পারফরম্যান্স সাবধানতা: JOIN ( SELECT ... )ভাল অনুকূলিত হয় না। JOINingসরাসরি টেবিলটি আরও ভাল কাজ করে (তবে এটি এখনও সমস্যাযুক্ত)।
রিক জেমস

3

আমি আশা করি আমি একটি পর্যাপ্ত সমাধান পেয়েছি। এটি এই নিবন্ধটি দ্বারা অনুপ্রাণিত ।

সংক্ষিপ্ত উত্তর:

  1. আমি সমস্ত বৈশিষ্ট্য সহ 1 টেবিল তৈরি করেছি। একটি বৈশিষ্ট্যের জন্য একটি কলাম। প্লাস প্রাথমিক কী কলাম।
  2. বৈশিষ্ট্য মানগুলি CSV- এর মতো ফর্ম্যাটে পাঠ্য কক্ষগুলিতে (সম্পূর্ণ পাঠ্য সন্ধানের জন্য) সঞ্চিত থাকে।
  3. পূর্ণ-পাঠ্য সূচী তৈরি করা হয়েছে। তার আগে বিভাগে (মাইআইএসএএম এর জন্য) এবং ফাইলে (ইনোডিবি এর জন্য ft_min_word_len=1) সেট করা গুরুত্বপূর্ণ, মাইএসকিএল পরিষেবাটি পুনরায় চালু করুন।[mysqld]innodb_ft_min_token_size=1my.cnf
  4. অনুসন্ধানের উদাহরণ: SELECT * FROM person_index WHERE MATCH(attribute_1) AGAINST("123 456 789" IN BOOLEAN MODE) LIMIT 1000কোথায় 123, 456একটি 789আইডি রয়েছে যা কোন ব্যক্তির সাথে যুক্ত হওয়া উচিত attribute_1। এই ক্যোয়ারীটি 1 সেকেন্ডের মধ্যে নিয়েছে।

বিস্তারিত উত্তর:

পদক্ষেপ 1. পূর্ণ পাঠ্য সূচী সহ টেবিল তৈরি করা। InnoDb মাইএসকিউএল 5.7 থেকে পূর্ণ পাঠ্য সূচীগুলি সমর্থন করে তাই আপনি যদি 5.5 বা 5.6 ব্যবহার করেন তবে আপনার মাইএসএএম ব্যবহার করা উচিত। এটি এএনটিবি-র চেয়ে কখনও কখনও এফটি অনুসন্ধানের পক্ষে আরও দ্রুত হয়।

CREATE TABLE `person_attribute_ft` (
  `person_id` int(11) NOT NULL,
  `attr_1` text,
  `attr_2` text,
  `attr_3` text,
  `attr_4` text,
  PRIMARY KEY (`person_id`),
  FULLTEXT KEY `attr_1` (`attr_1`),
  FULLTEXT KEY `attr_2` (`attr_2`),
  FULLTEXT KEY `attr_3` (`attr_3`),
  FULLTEXT KEY `attr_4` (`attr_4`),
  FULLTEXT KEY `attr_12` (`attr_1`,`attr_2`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

পদক্ষেপ 2. EAV (সত্তা-বৈশিষ্ট্য-মান) সারণী থেকে ডেটা .োকান। উদাহরণস্বরূপ প্রশ্নে বর্ণিত এটি 1 টি সাধারণ এসকিউএল দিয়ে করা যেতে পারে:

INSERT IGNORE INTO `person_attribute_ft`
SELECT
    p.person_id,
    (SELECT GROUP_CONCAT(a.attribute_value SEPARATOR ' ') FROM attribute a WHERE a.attribute_type_id = 1 AND a.person_id = p.person_id LIMIT 10) attr_1,
    (SELECT GROUP_CONCAT(a.attribute_value SEPARATOR ' ') FROM attribute a WHERE a.attribute_type_id = 2 AND a.person_id = p.person_id LIMIT 10) attr_2,
    (SELECT GROUP_CONCAT(a.attribute_value SEPARATOR ' ') FROM attribute a WHERE a.attribute_type_id = 3 AND a.person_id = p.person_id LIMIT 10) attr_3,
    (SELECT GROUP_CONCAT(a.attribute_value SEPARATOR ' ') FROM attribute a WHERE a.attribute_type_id = 4 AND a.person_id = p.person_id LIMIT 10) attr_4
FROM person p

ফলাফলটি এমন কিছু হওয়া উচিত:

mysql> select * from person_attribute_ft limit 10;
+-----------+--------+--------+--------+--------+
| person_id | attr_1 | attr_2 | attr_3 | attr_4 |
+-----------+--------+--------+--------+--------+
|         1 | 541    | 2      | 1927   | 3      |
|         2 | 2862   | 2      | 1939   | 4      |
|         3 | 6573   | 2      | 1904   | 2      |
|         4 | 2432   | 1      | 2005   | 2      |
|         5 | 2208   | 1      | 1995   | 4      |
|         6 | 8388   | 2      | 1973   | 1      |
|         7 | 107    | 2      | 1909   | 4      |
|         8 | 5161   | 1      | 2005   | 1      |
|         9 | 8022   | 2      | 1953   | 4      |
|        10 | 4801   | 2      | 1900   | 3      |
+-----------+--------+--------+--------+--------+
10 rows in set (0.00 sec)

পদক্ষেপ 3. এই জাতীয় প্রশ্নের সাথে টেবিল থেকে নির্বাচন করুন:

mysql> SELECT SQL_NO_CACHE *
    -> FROM `person_attribute_ft`
    -> WHERE 1 AND MATCH(attr_1) AGAINST ("3000 3001 3002 3003 3004 3005 3006 3007" IN BOOLEAN MODE)
    -> AND MATCH(attr_2) AGAINST ("1" IN BOOLEAN MODE)
    -> AND MATCH(attr_3) AGAINST ("1980 1981 1982 1983 1984" IN BOOLEAN MODE)
    -> AND MATCH(attr_4) AGAINST ("2,3" IN BOOLEAN MODE)
    -> LIMIT 10000;
+-----------+--------+--------+--------+--------+
| person_id | attr_1 | attr_2 | attr_3 | attr_4 |
+-----------+--------+--------+--------+--------+
|     12131 | 3002   | 1      | 1982   | 2      |
|     51315 | 3007   | 1      | 1984   | 2      |
|    147283 | 3001   | 1      | 1984   | 2      |
|    350086 | 3005   | 1      | 1982   | 3      |
|    423907 | 3004   | 1      | 1982   | 3      |
... many rows ...
|   9423907 | 3004   | 1      | 1982   | 3      |
|   9461892 | 3007   | 1      | 1982   | 2      |
|   9516361 | 3006   | 1      | 1980   | 2      |
|   9813933 | 3005   | 1      | 1982   | 2      |
|   9986892 | 3003   | 1      | 1981   | 2      |
+-----------+--------+--------+--------+--------+
90 rows in set (0.17 sec)

ক্যোয়ারী সমস্ত সারি নির্বাচন করে:

  • এর মধ্যে কমপক্ষে একটি আইডি মিলছে attr_1:3000, 3001, 3002, 3003, 3004, 3005, 3006 or 3007
  • এবং একই সময় ম্যাচিং এ 1মধ্যে attr_2(এই কলাম প্রতিনিধিত্ব করে লিঙ্গ তাই যদি এই সমাধান কাস্টমাইজড করা হয়েছে, এটি হওয়া উচিত smallint(1)সহজ সূচকের সাথে, ইত্যাদি ...)
  • এবং অন্তত একটি একই সময় ম্যাচিং এ 1980, 1981, 1982, 1983 or 1984মধ্যেattr_3
  • এবং একই সাথে মিলছে 2বা 3ইনattr_4

উপসংহার:

আমি জানি এই সমাধানটি অনেক পরিস্থিতিতে নিখুঁত এবং আদর্শ নয় তবে EAV টেবিল ডিজাইনের জন্য ভাল বিকল্প হিসাবে ব্যবহার করা যেতে পারে।

আমি আশা করি এটি কাউকে সাহায্য করবে।


1
আমি এটি খুব অসম্ভব বলে মনে করি যে এই নকশাটি আপনার মূল নকশার চেয়ে কমপোজিট সূচকগুলির সাথে আরও ভাল সম্পাদন করবে। এগুলি তুলনা করার জন্য আপনি কোন পরীক্ষাগুলি করেছেন?
ypercubeᵀᴹ

0

কোয়েরি সূচক ইঙ্গিতগুলি উপযুক্ত মনে হচ্ছে ব্যবহার করে দেখুন

মাইএসকিএল সূচক ইঙ্গিত


1
ইঙ্গিতগুলি ক্যোয়ারির একটি সংস্করণে সহায়তা করতে পারে তবে অন্যটিকে আঘাত করে। নোট করুন যে অপটিমাইজার জন্মগত বছর সেরা প্রথম টেবিল হিসাবে বেছে নিয়েছে, সম্ভবত যদি সবচেয়ে অনাকাঙ্ক্ষিত সারিগুলি ফিল্টার করা হয়।
রিক জেমস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.