এমওয়াইএসকিউএল উচ্চতর লিমিটেড কেন অনুসন্ধানকে ধীর করে দেয়?


173

সংক্ষেপে সংক্ষেপে: ১ million মিলিয়নেরও বেশি রেকর্ড [২ জিবি আকারের) সহ একটি টেবিল। * প্রাথমিক_কি * দ্বারা অর্ডার ব্যবহার করার সময় উচ্চতর সীমাবদ্ধ নির্বাচন সহ অফসেট, কোয়েরিটি ধীরে ধীরে হয়ে যায়

সুতরাং

SELECT * FROM large ORDER BY `id`  LIMIT 0, 30 

তুলনায় অনেক কম লাগে

SELECT * FROM large ORDER BY `id` LIMIT 10000, 30 

এটি কেবল 30 টি রেকর্ড এবং একইভাবে আদেশ দেয়। সুতরাং এটি অর্ডার দ্বারা ওভারহেড নয়।
এখন সর্বশেষ 30 টি সারি আনার সময় এটি প্রায় 180 সেকেন্ড সময় নেয়। আমি কীভাবে এই সহজ ক্যোয়ারীটি অনুকূল করতে পারি?


দ্রষ্টব্য: আমি লেখক। মাইএসকিউএল উপরের ক্ষেত্রে সূচক (প্রাথমিক) উল্লেখ করে না। ব্যাখ্যার জন্য "Quassnoi" ব্যবহারকারীর নীচের লিঙ্কটি দেখুন।
রহমান

উত্তর:


197

এটি স্বাভাবিক যে উচ্চতর অফসেটগুলি ক্যোয়ারিকে ধীর করে দেয়, যেহেতু ক্যোয়ারিকে প্রথম OFFSET + LIMITরেকর্ডগুলি গণনা করতে হবে (এবং কেবলমাত্র LIMITসেগুলি গ্রহণ করুন)। এই মানটি যত বেশি হবে, তত দীর্ঘতর ক্যোয়ারি চলে।

ক্যোয়ারী ডানদিকে যেতে পারে না OFFSETকারণ প্রথমত, রেকর্ডগুলি বিভিন্ন দৈর্ঘ্যের হতে পারে এবং দ্বিতীয়ত, মুছে ফেলা রেকর্ড থেকে ফাঁক থাকতে পারে। এটি প্রতিটি রেকর্ড তার পথে পরীক্ষা করে গণনা করা প্রয়োজন।

Assuming যে idএকটি PRIMARY KEYএকটি এর MyISAMটেবিল আপনি এটি এই কৌতুক ব্যবহার করে গতি বাড়াতে পারেন:

SELECT  t.*
FROM    (
        SELECT  id
        FROM    mytable
        ORDER BY
                id
        LIMIT 10000, 30
        ) q
JOIN    mytable t
ON      t.id = q.id

এই নিবন্ধটি দেখুন:


7
মাইএসকিউএল "প্রারম্ভিক সারি অনুসন্ধান" আচরণটি কেন এতক্ষণ কথা বলছিল তার উত্তর। আপনার সরবরাহিত কৌতুক দ্বারা, কেবল ম্যাচড আইডিগুলি (সরাসরি সূচক অনুসারে) আবদ্ধ থাকে, অনেকগুলি রেকর্ডের অপরিশোধিত সারি লুকআপ সংরক্ষণ করে। সেই কৌতুকটি হুররে!
রহমান

4
@ হারাল্ড: "কাজ না করা" বলতে আপনার অর্থ কী? এটি একটি খাঁটি পারফরম্যান্স উন্নতি। যদি কোনও সূচকগুলি ব্যবহারের যোগ্য না হয় ORDER BYবা সূচকগুলি আপনার প্রয়োজনীয় সমস্ত ক্ষেত্রকে কভার করে, আপনার এই পরিশ্রমের প্রয়োজন হবে না।
কাসনসুই

6
@ f055: উত্তরটি "তাত্ক্ষণিক" নয়, "গতি বাড়িয়ে" বলেছে। আপনি কি উত্তরের প্রথম বাক্যটি পড়েছেন?
কাসনসুই

3
InnoDB এর জন্য কি এমন কিছু চালানো সম্ভব?
নেভারইন্ডিংউইউ

3
@ লান্তি: দয়া করে এটি একটি পৃথক প্রশ্ন হিসাবে পোস্ট করুন এবং এটি ট্যাগ করতে ভুলবেন না postgresql। এটি একটি মাইএসকিউএল-নির্দিষ্ট উত্তর।
কাসনসুই

220

আমারও ঠিক একই সমস্যা ছিল। আপনি এই ডেটা একটি বৃহত পরিমাণে সংগ্রহ করতে চান এবং এই যে কোনও নির্দিষ্ট 30 টি সংগ্রহ না করে আপনি সম্ভবত একটি লুপ চালাবেন এবং 30 দ্বারা অফসেটটি বাড়িয়ে তুলবেন fact

পরিবর্তে আপনি যা করতে পারেন তা হ'ল:

  1. ডেটার সেট (30) এর শেষ আইডি ধরে রাখুন (যেমন লাস্টআইডি = 530)
  2. শর্ত যুক্ত করুন WHERE id > lastId limit 0,30

সুতরাং আপনি সর্বদা একটি জিরো অফসেট রাখতে পারেন। পারফরম্যান্সের উন্নতি দেখে আপনি অবাক হয়ে যাবেন।


শূন্যতা থাকলে এই কাজ করে? আপনার যদি একটি একক অনন্য কী (উদাহরণস্বরূপ একটি যৌগিক কী) না থাকে তবে কী হবে?
xaisoft

8
আপনার ফলাফল সেটটি যদি সেই কী দ্বারা বাছাই করা হয় তবে কেবল এটিই কাজ করে তা সবার জন্যই স্পষ্ট না হতে পারে (উতরাই ক্রমের জন্য একই ধারণাটি কাজ করে তবে পরিবর্তনটি> লাস্টিডে পরিবর্তন করুন) এটি যদি তা হয় তবে কিছু যায় আসে না প্রাথমিক কী বা অন্য কোনও ক্ষেত্র (বা ক্ষেত্রের গ্রুপ
এলফ

ভাল করেছো লোকটা! একটি খুব সহজ সমাধান যা আমার সমস্যার সমাধান করেছে :-)
ওডাভিড

30
সীমাবদ্ধতা / অফসেটটি প্রায়শই পৃষ্ঠাবদ্ধযুক্ত ফলাফলগুলিতে ব্যবহৃত হয় এবং লাস্টআইড হোল্ডিং কেবল সম্ভব নয় কারণ ব্যবহারকারী যে কোনও পৃষ্ঠায় যেতে পারে, পরের পৃষ্ঠায় সর্বদা না। অন্য কথায়, অফসেটটি অবিচ্ছিন্ন নিদর্শন অনুসরণ না করে প্রায়শই পৃষ্ঠা এবং সীমাবদ্ধতার ভিত্তিতে গতিশীলভাবে গণনা করা প্রয়োজন।
টম


17

মাইএসকিউএল সরাসরি 10000 তম রেকর্ডে যেতে পারে না (বা আপনার পরামর্শ হিসাবে 80000 তম বাইট) কারণ এটি ধরে নিতে পারে না যে এটি প্যাক করা / অর্ডার করা হয়েছে (বা এটির 1 থেকে 10000 অবিরত মান রয়েছে)। যদিও এটি বাস্তবে এটি হতে পারে তবে মাইএসকিউএল ধরে নিতে পারে না যে কোনও গর্ত / ফাঁক / মুছে ফেলা আইডি নেই।

সুতরাং, যেমন ববস লক্ষ করেছেন, মাইএসকিউএল id30 ফিরিয়ে দেওয়ার আগে 10000 সারি (বা সূচকের 10000 তম এন্ট্রিগুলির মধ্য দিয়ে যেতে হবে ) আনতে হবে ।

সম্পাদনা : আমার বক্তব্য চিত্রিত করার জন্য

নোট করুন যদিও

SELECT * FROM large ORDER BY id LIMIT 10000, 30 

ধীর হয়ে যাবে (ইর) ,

SELECT * FROM large WHERE id >  10000 ORDER BY id LIMIT 30 

হবে দ্রুত (ER) , এবং একই ফলাফল প্রদান করা কোন অনুপস্থিত আছে ফিরে আসবে idগুলি (অর্থাত ফাঁক)।


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

1
আপনি যদি আইডিতে একটি বিভাজন ব্যবহার করেন তবে এটি ঠিক সেই চিহ্নটিতে যেতে পারে। যাইহোক, আপনি যদি এটিতে কোনও সীমাবদ্ধতা রাখেন, আইডি দ্বারা অর্ডার করা হয় তবে এটি শুরুর তুলনায় কেবল একটি আপেক্ষিক কাউন্টার, সুতরাং এটি পুরোপুরি ট্রান্সভার্স করতে হবে।
রিডসিও

খুব ভাল নিবন্ধ eversql.com/…
পাউআউট

আমার জন্য কাজ করেছেন রিডসিও ধন্যবাদ
মহেশ কাজল

8

আমি লিমিটেড এক্স, ওয়াই এর আইডি বাছাই করে বেছে বেছে অনুসন্ধানগুলি অনুকূল করতে একটি আকর্ষণীয় উদাহরণ পেয়েছি। আমার কাছে 35 মিলিয়ন সারি রয়েছে তাই সারিগুলির একটি সীমা পেতে 2 মিনিটের মতো সময় লেগেছে।

কৌশলটি এখানে:

select id, name, address, phone
FROM customers
WHERE id > 990
ORDER BY id LIMIT 1000;

সর্বশেষ আইডি দিয়ে কেবল WHERE রাখুন আপনি পারফরম্যান্সটি অনেক বাড়িয়েছেন। আমার জন্য এটি ছিল 2 মিনিট থেকে 1 সেকেন্ড :)

অন্যান্য আকর্ষণীয় কৌশল এখানে: http://www.iheavy.com/2013/06/19/3-ways-to-optimize-for-pages-in-mysql/

এটি স্ট্রিং দিয়েও কাজ করে


1
এটি কেবলমাত্র টেবিলের জন্য কাজ করে, যেখানে কোনও ডেটা মুছে ফেলা হয় না
miro

1
@ এমিরো এটি সত্য তবেই যদি আপনি এই ধারণা অনুযায়ি কাজ করছেন যে আপনার ক্যোয়ারী এলোমেলো পৃষ্ঠাগুলিতে লকআপ করতে পারে, যা আমি বিশ্বাস করি না যে এই পোস্টারটি ধরেছে। যদিও আমি বেশিরভাগ বাস্তব বিশ্বের কেসগুলির জন্য এই পদ্ধতিটি পছন্দ করি না, যতক্ষণ না আপনি সর্বদা এটি সর্বশেষ প্রাপ্ত আইডিটি বন্ধ করে রাখছেন ততক্ষণ এই ফাঁকগুলি দিয়ে কাজ করবে।
গ্রিমিও

5

দুটি প্রশ্নের সময়োপযোগী অংশটি সারণী থেকে সারিগুলি পুনরুদ্ধার করছে। যৌক্তিকভাবে বলতে গেলে, LIMIT 0, 30সংস্করণে, কেবলমাত্র 30 টি সারি পুনরুদ্ধার করা দরকার। ইন LIMIT 10000, 30সংস্করণ, 10000 সারি মূল্যায়ন করা হয় এবং 30 সারি ফিরিয়ে আনা হয়। আমার ডেটা-রিডিং প্রক্রিয়াটি কিছু অপ্টিমাইজেশন হতে পারে তবে নিম্নলিখিতগুলি বিবেচনা করুন:

প্রশ্নগুলির যদি আপনার একটি সার্বিক ধারা থাকে? ইঞ্জিনটিকে অবশ্যই উপযুক্ত সমস্ত সারি ফেরত দিতে হবে এবং তারপরে ডেটা বাছাই করতে হবে এবং শেষ পর্যন্ত 30 টি সারি পাওয়া উচিত।

অর্ডার বাই ক্রমানুসারে সারিগুলি প্রক্রিয়াজাত করা হয় না সেই ক্ষেত্রেও বিবেচনা করুন। কোন সারিগুলি ফিরে আসবে তা নির্ধারণ করতে সমস্ত যোগ্যতার সারিগুলি বাছাই করতে হবে।


1
শুধু ভাবছি কেন এই 10000 সারি আনতে সময় ব্যয় করে। সেই ক্ষেত্রটিতে ব্যবহৃত সূচক (আইডি, যা একটি প্রাথমিক কী) রেকর্ড নংয়ের জন্য সেই পিকে সূচক চেয়ে যত দ্রুত তাড়াতাড়ি সেই সারিগুলি পুনরুদ্ধার করা উচিত। ১০০০০০, যার পরিবর্তে সূচী রেকর্ড দৈর্ঘ্যের দ্বারা গুণিত অফসেটের ফাইলটি অনুসন্ধানের জন্য দ্রুত হওয়া উচিত, (যেমন, 10000 * 8 = বাইট নং 80000 - এটি 8 সূচক রেকর্ড দৈর্ঘ্য প্রদত্ত)
রহমান

@ রহমান - ১০০০০০ সারি পেরিয়ে যাওয়ার একমাত্র উপায় হ'ল একের পর এক তার উপর দিয়ে যাওয়া। এটি কেবল একটি সূচককে জড়িত করতে পারে তবে তবুও সূচী সারিগুলি সময় দিতে সময় নেয়। নেই কোন MyISAM বা InnoDB কাঠামোই সঠিকভাবে (সব ক্ষেত্রে) "চাইতে" করতে পারেন রেকর্ড করতে 10000. 10000 * 8 পরামর্শ অনুমান (1) MyISAM, (2) নির্দিষ্ট দৈর্ঘ্যের রেকর্ড, এবং (3) টেবিল থেকে কখনো কোনো মোছাগুলিকে । যাইহোক, মাইআইএসএএম সূচকগুলি বিটিরিস, সুতরাং এটি কার্যকর হবে না।
রিক জেমস

যেমন এই উত্তরটি বলেছে, আমি বিশ্বাস করি, সত্যই ধীর অংশটি সারি অনুসন্ধান, সূচীগুলি অনুসরণ না করে (অবশ্যই এটিও যোগ করবে তবে ডিস্কে সারি লুপ اپের মতো কোথাও নেই)। এই ইস্যুটির জন্য সরবরাহ করা কর্মপরিকল্পনাগুলির উপর ভিত্তি করে, আমি বিশ্বাস করি যে আপনি যদি সূচকের বাইরে কলামগুলি বেছে নিচ্ছেন তবে সারি লকআপগুলি ঘটবে they এমনকি যদি তারা অনুচ্ছেদে বা যেখানে ধারা দ্বারা অর্ডের অংশ না হয়। এটি প্রয়োজনীয় হওয়ার জন্য আমি কোনও কারণ খুঁজে পাইনি, তবে দেখা যাচ্ছে যে কিছু কাজের ক্ষেত্র কেন সহায়তা করে।
গ্রিমিও

1

যারা তুলনা এবং পরিসংখ্যান আগ্রহী তাদের জন্য :)

পরীক্ষা 1: ডেটাসেটটিতে প্রায় 100 মিলিয়ন সারি রয়েছে। প্রতিটি সারিতে বেশ কয়েকটি বিজিআইএনটি, টিনআইএনটি পাশাপাশি দুটি টেক্সট ক্ষেত্র রয়েছে (ইচ্ছাকৃতভাবে) প্রায় 1 কে চর রয়েছে।

  • নীল: = SELECT * FROM post ORDER BY id LIMIT {offset}, 5
  • কমলা: = @ কাসনোইয়ের পদ্ধতি। SELECT t.* FROM (SELECT id FROM post ORDER BY id LIMIT {offset}, 5) AS q JOIN post t ON t.id = q.id
  • অবশ্যই, তৃতীয় পদ্ধতিটি, ... WHERE id>xxx LIMIT 0,5এখানে উপস্থিত হয় না কারণ এটি ধ্রুবক সময় হওয়া উচিত।

পরীক্ষা 2: অনুরূপ জিনিস, এক সারিতে কেবল 3 বিগিন্ট রয়েছে।

  • সবুজ: = আগে নীল
  • red: = কমলা আগে

এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.