মাইএসকিউএল: সারি সংখ্যা গণনা করার দ্রুততম উপায়


117

মাইএসকিউএলে বেশ কয়েকটি সারি গণনা করার উপায়টি দ্রুত হওয়া উচিত?

এই:

SELECT COUNT(*) FROM ... WHERE ...

বা, বিকল্প:

SELECT 1 FROM ... WHERE ...

// and then count the results with a built-in function, e.g. in PHP mysql_num_rows()

কেউ ভাবেন যে প্রথম পদ্ধতিটি দ্রুত হওয়া উচিত, কারণ এটি স্পষ্টতই ডাটাবেস অঞ্চল এবং ডাটাবেস ইঞ্জিনটি অভ্যন্তরীণভাবে এই জাতীয় জিনিস নির্ধারণের সময় অন্য কারও চেয়ে দ্রুত হওয়া উচিত।


1
ওহ, আমি একটি অনুরূপ প্রশ্ন পেয়েছি ( স্ট্যাকওভারফ্লো . com / প্রশ্নস / 1855226/… )। কিন্তু তারপর, আমি ব্যবহার SELECT 1এবং SELECT *। পার্থক্য আছে কি?
ফ্রাঞ্জ

আমি জানি না, তবে অনুমানযোগ্য যে এই দুটি উত্তর একরকম - মাইএসকিএল কোয়েরি অপ্টিমাইজার প্রতিটি ক্ষেত্রে একই কাজ করতে পারে। যে বলেছিল যে পূর্ববর্তীটি তার চেয়ে কম অস্পষ্ট। কেন আপনি কিছু মানদণ্ড লিখে তা পরীক্ষা করে দেখেন না?
জেসি কোহেন

আহ, আসুন ধরে নেওয়া যাক আমি বিভিন্ন কথায় অনুরূপ প্রশ্ন জিজ্ঞাসা করে এসও এর অনুসন্ধান ইঞ্জিনটির দৃশ্যমানতা বাড়ানোর চেষ্টা করছি;)
ফ্রানজ

1
পার্থক্য হ'ল পিএইচপি সাইডে প্রেরিত ডেটার পরিমাণ। আপনার যত বেশি কলাম রয়েছে, ধীরে ধীরে নির্বাচন * নির্বাচন করুন 1 নির্বাচন করুন, কারণ সমস্ত কলামগুলি কেবল ১ নম্বর 1 এর পরিবর্তে পুনরুদ্ধার করা হবে mysql_query(), উদাহরণস্বরূপ, আপনি যখন চালান , পুরো ফলাফল সেটটি মাইএসকিউএল থেকে পিএইচপিকে প্রেরণ করা হবে, আপনি যা নির্বিশেষেই করুন set যে তথ্য দিয়ে না।
toon81

অন্তর্দৃষ্টি বা নতুন ধারণা অর্জনের জন্য এই জাতীয় একটি প্রশ্ন জিজ্ঞাসা করা একটি দুর্দান্ত উপায়, তবে শেষ পর্যন্ত যদি আপনার আরও নির্দিষ্ট গতি থাকে যেখানে আপনি আরও গতি চান, আপনার দ্রুততম কি তা পরীক্ষা করতে আপনাকে পরীক্ষা চালাতে হবে।
এখনও_ড্রিমিং_1

উত্তর:


124

আপনি যখন COUNT(*)এটি গণনা কলাম সূচিতে নিয়ে যান, তাই এটি সেরা ফলাফল হবে। মাইআইএসএএম ইঞ্জিন সহ মাইএসকিএল আসলে সারি গণনা সংরক্ষণ করে, আপনি যখনই সমস্ত সারি গণনা করার চেষ্টা করবেন তখন এটি সমস্ত সারি গণনা করে না। (প্রাথমিক কী এর কলামের উপর ভিত্তি করে)

সারিগুলি গণনা করতে পিএইচপি ব্যবহার করা খুব স্মার্ট নয়, কারণ আপনাকে পিএইচপি থেকে mysql থেকে ডেটা প্রেরণ করতে হবে। আপনি যখন মাইএসকিএল পক্ষের ক্ষেত্রে এটি অর্জন করতে পারেন তবে কেন এটি করবেন?

যদি COUNT(*)ধীর গতি EXPLAINহয় তবে আপনার ক্যোয়ারিতে চালানো উচিত এবং সূচীগুলি সত্যই ব্যবহৃত হয়েছে কিনা এবং সেগুলি কোথায় যুক্ত করা উচিত তা পরীক্ষা করা উচিত।


নিম্নলিখিতটি দ্রুততম উপায় নয়, তবে একটি কেস রয়েছে, যেখানে COUNT(*)সত্যিই ফিট হয় না - যখন আপনি ফলাফলগুলি গোষ্ঠীকরণ শুরু করেন, আপনি সমস্যার মধ্যে পড়ে যেতে পারেন, যেখানে COUNTসত্যই সমস্ত সারি গণনা করা হয় না।

সমাধানটি হ'ল SQL_CALC_FOUND_ROWS। এটি সাধারণত ব্যবহৃত হয় যখন আপনি সারিগুলি নির্বাচন করছেন তবে এখনও মোট সারির গণনাটি জানতে হবে (উদাহরণস্বরূপ, পেজিংয়ের জন্য)। আপনি যখন ডাটা সারিগুলি নির্বাচন করেন, কেবল SQL_CALC_FOUND_ROWSনির্বাচনের পরে কীওয়ার্ডটি যুক্ত করুন:

SELECT SQL_CALC_FOUND_ROWS [needed fields or *] FROM table LIMIT 20 OFFSET 0;

আপনি প্রয়োজনীয় সারিগুলি নির্বাচন করার পরে, আপনি এই একক ক্যোয়ারির সাথে গণনাটি পেতে পারেন:

SELECT FOUND_ROWS();

FOUND_ROWS() ডেটা বাছাইয়ের প্রশ্নের পরে অবিলম্বে ফোন করতে হবে।


উপসংহারে, সমস্ত কিছুই আসলে আপনার কয়টি এন্ট্রি রয়েছে এবং WHERE বিবৃতিতে রয়েছে তা নেমে আসে। প্রচুর সারি রয়েছে (যখন কয়েক হাজার, লক্ষ লক্ষ এবং তার বেশি) তখন সূচাগুলি কীভাবে ব্যবহৃত হচ্ছে সেদিকে আপনার সত্যই মনোযোগ দেওয়া উচিত।


14
সংশোধন: MyISAMসারি গণনা সঞ্চয় করে। অন্যান্য স্টোরেজ ইঞ্জিনগুলি পছন্দ করেInnoDB সারি গণনা সঞ্চয় করে না এবং প্রতিবার সমস্ত সারি গণনা করবে
স্ক্রম মিস্টার 0

1
আপনি কি জানেন যে কোনটি সর্বাপেক্ষা দ্রুত হবে যখন আপনি কেবল সারি আছে কিনা তা সন্ধান করতে চান: SELECT 1 FROM ... LIMIT 1বা SELECT COUNT(*) FROM ...?
ফ্র্যাঞ্জ

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

6
ইঞ্জিনটি সারি গণনা করে কিনা তা অপ্রাসঙ্গিক। প্রশ্নটি পরিষ্কারভাবে জানিয়েছে যে এখানে একটি WHEREধারা রয়েছে।
আলভারো গঞ্জালেজ

1
@ ফ্র্যাঞ্জ SELECT COUNT(*) FROM ...যা স্ক্যান করতে হবে তার উপর নির্ভর করে যথেষ্ট সময় নিতে পারে (উদাহরণস্বরূপ একটি খুব বড় টেবিল বা লক্ষ লক্ষ / বিলিয়ন / ট্রিলিয়ন সারি সূচক)। SELECT 1 FROM ... LIMIT 1অবিলম্বে ফিরে আসে কারণ আপনি এটিকে প্রথম সারিতে সীমাবদ্ধ রেখেছেন।
jbo5112

59

আমার সতীর্থদের সাথে কথা বলার পরে, রিকার্ডো আমাদের বলেছিলেন যে দ্রুততম পথটি হ'ল:

show table status like '<TABLE NAME>' \G

তবে আপনাকে মনে রাখতে হবে ফলাফলটি সঠিক নাও হতে পারে।

আপনি এটি কমান্ড লাইন থেকেও ব্যবহার করতে পারেন:

$ mysqlshow --status <DATABASE> <TABLE NAME>

আরও তথ্য: http://dev.mysql.com/doc/refman/5.7/en/show-table-status.html

এবং আপনি mysqlperformanceblog এ একটি সম্পূর্ণ আলোচনা খুঁজে পাবেন


2
InnoDB এর জন্য এটি একটি আনুমানিক।
মার্টিন টর্নয়েজ

2
যখন খুব বড় টেবিলগুলিতে গণনা (*) আক্ষরিক অর্থে কয়েক ঘন্টা সময় নিতে পারে সেখানে সারিগুলির সংখ্যার সম্পর্কে মোটামুটি ধারণা প্রয়োজন যখন এটি জানতে পেরেছি!
হানসেন

এটি আমার সমস্ত চুলগুলি টেনে আনতে আমাকে রক্ষা করেছিল। COUNT (*) আমার ডেটাবেজে সমস্ত 33 মিলিয়ন প্লাস সারি গণনা করতে যুগে যুগে সময় নিচ্ছিল। যাইহোক, আমি কেবলমাত্র জানতে চেয়েছিলাম যে আমার সমান্তরাল মুছে ফেলা সারিগুলির ফাংশনটি কাজ করছে কিনা। আমার সঠিক সংখ্যা দরকার ছিল না।
joemar.ct

1
পরিবর্তে "COUNT (*)" সারণির স্থিতি ব্যবহার করা এই প্রশ্নের সঠিক উত্তর হওয়া উচিত যেমন "দ্রুততম" নয় "নির্ভুলতা" সম্পর্কে।
Lepe

2
ব্যবহার SHOW TABLE STATUS(বা সমমানের SELECTমধ্যে information_schema) দ্রুত, কিন্তু এটি একটি হ্যান্ডেল নেই WHEREদফা। এটি মাইআইএসএএমের জন্য সুনির্দিষ্ট, তবে ইনোডিবি-র ক্ষেত্রে অসম্পূর্ণ (কখনও কখনও 2 এর ফ্যাক্টর দ্বারা বন্ধ)।
রিক জেমস

29

দুর্দান্ত প্রশ্ন, দুর্দান্ত উত্তর। যদি কেউ এই পৃষ্ঠাটি পড়ছে এবং সেই অংশটি হারিয়ে ফেলছে তবে ফলাফল প্রতিধ্বনিত করার একটি দ্রুত উপায়:

$counter = mysql_query("SELECT COUNT(*) AS id FROM table");
$num = mysql_fetch_array($counter);
$count = $num["id"];
echo("$count");

5
পিএইচপি 5.5.0 হিসাবে mysql_query একটি অবচিত কাজ।
ওমর তারিক

8
না কেন as count? idপ্রথম চেহারাতে বিভ্রান্তিকর হয়।
ওর্খন আলিখনভ

প্রশ্নের উত্তর দেয় না
মানসিকভাবে

17

এই ক্যোয়ারী (যা বায়ুয়াহ পোস্টের অনুরূপ ) একটি ডাটাবেসের মধ্যে সমস্ত সারণী গণনা করার একটি দুর্দান্ত সংক্ষিপ্তসার দেখায়: ( ইভান কচিকাটারি দ্বারা সঞ্চিত পদ্ধতির সহজ সংস্করণ যা আমি অত্যন্ত সুপারিশ করি)।

SELECT TABLE_NAME AS 'Table Name', TABLE_ROWS AS 'Rows' FROM information_schema.TABLES WHERE TABLES.TABLE_SCHEMA = '`YOURDBNAME`' AND TABLES.TABLE_TYPE = 'BASE TABLE'; 

উদাহরণ:

+-----------------+---------+
| Table Name      | Rows    |
+-----------------+---------+
| some_table      |   10278 |
| other_table     |     995 |

এটি আমাকে একটি ফলাফল দেয়। তবে গণনা থেকে ফলাফল (1) এবং এটি এক। এই উপায় গণনা কোয়েরির চেয়ে সর্বদা কম নম্বর দেয়। কোন চিন্তা?
আইয়্যাপ্পান সেকার

3
পাঠকদের জন্য কেবল একটি নোট। এই পদ্ধতিটি অত্যন্ত দ্রুত তবে এটি কেবল তখনই প্রযোজ্য যখন আপনি আনুমানিক সংখ্যক সারিগুলির সাথে কাজ করতে পারবেন যেহেতু সঞ্চিত মানটি ইনোডিবি ব্যবহারের ক্ষেত্রে যে information_schemaফিরিয়েছে তার সাথে একই হবে না SELECT count(*) FROM। আপনার যদি কঠোর মান প্রয়োজন হয় তবে মনে রাখবেন যে এই পদ্ধতিটি কেবল মাইআইএসএএম টেবিলের সাথেই কঠোর মান দেয়। InnoDB এর সাথে সারিগুলির সংখ্যা মোটামুটি প্রায়।
বার্তোসজ ফিরিন

13

আমি সর্বদা বুঝতে পেরেছি যে নীচে আমাকে দ্রুততম প্রতিক্রিয়া সময় দেবে।

SELECT COUNT(1) FROM ... WHERE ...

1
1 টি থেকে নির্বাচন করবেন না ... কোথায় ... আরও দ্রুত হতে হবে?
প্যাট্রিক

3
@ পেট্রিক - SELECT 1 ... সারি ফিরে আসবে WHEREএবং LIMITজিজ্ঞাসা করবে এবং সেগুলি সমস্ত "1" হবে।
রিক জেমস

1
show table status like '<TABLE NAME>' এটি আরও দ্রুত হবে।
গভীর

@ প্রদীপ - তবে আপনার কাছে কোনও WHEREধারা থাকলে প্রাসঙ্গিক নয় । এবং, InnoDB এর পক্ষে এটি কেবল অনুমান।
রিক জেমস

@ রিকজেমস হ্যাঁ সত্য!
গভীর

6

আপনার যদি পুরো ফলাফলের সেটটি গণনা করতে হয় তবে আপনি নীচের পদ্ধতিটি গ্রহণ করতে পারেন:

SELECT SQL_CALC_FOUND_ROWS * FROM table_name LIMIT 5;
SELECT FOUND_ROWS();

এটি সাধারণত ব্যবহারের চেয়ে দ্রুত হয় না COUNT তবে কেউ মনে করতে পারে বিপরীতটি কারণ এটি অভ্যন্তরীণভাবে গণনা করছে এবং ব্যবহারকারীর কাছে ডেটা ফেরত পাঠায় না সুতরাং পারফরম্যান্সের উন্নতির সন্দেহ হয়।

এই দুটি কোয়েরি করা মোটামুটি পাওয়ার জন্য পৃষ্ঠাগুলি জন্য ভাল তবে বিশেষত WHEREধারাগুলি ব্যবহারের জন্য নয় ।


আহা। এটি কি খুব সাধারণ ডাটাবেস সিস্টেম জুড়ে কাজ করে? মাইএসকিউএল, পোস্টগ্রিস, এসকিউএলাইট ...?
ফ্রানজ

4
এটি আসলে প্রায়শই COUNT (*) ব্যবহারের চেয়ে দ্রুত হয় না। দেখুন stackoverflow.com/questions/186588/...
toon81

2
এই ফাংশনটি ব্যবহার করার সময় আপনার খুব সতর্ক হওয়া উচিত। এর বেপরোয়া ব্যবহার একবারে আমাদের পুরো উত্পাদন পরিবেশকে গ্রাইন্ডিং স্টলে নিয়ে আসে। এটি অত্যন্ত সংস্থানযুক্ত, তাই যত্ন সহ ব্যবহার করুন।
জ্যানিস পিসেনিকস

6

আমি কিছু benchmarks করেনি চালু হওয়ার সময়ের তুলনা করতে COUNT(*)বনাম COUNT(id)(- ইন্ডেক্স আইডি টেবিলের প্রাথমিক কী যায়)।

পরীক্ষার সংখ্যা: 10 * 1000 ক্যোয়ারী

ফলাফল: COUNT(*)দ্রুত 7%

গ্রাফ দেখুন: মাপদণ্ড

আমার পরামর্শ ব্যবহার করতে হয়: SELECT COUNT(*) FROM table


1
এফওয়াইআই এর সাথে গণনা করার একটি সাধারণ উপায় রয়েছে COUNT(1), সেখানে কিছু মানদণ্ডগুলি দেখতে আকর্ষণীয় হবে ...
স্লিক

4

এটা চেষ্টা কর:

SELECT
    table_rows "Rows Count"
FROM
    information_schema.tables
WHERE
    table_name="Table_Name"
AND
    table_schema="Database_Name";

@ লেপ আমি দুঃখিত আমি বোঝাতে চাইছিলাম, যদি কেউ নীচে চাপ দিয়ে কাজ করে সে কেন সে তা করে তার কিছু ব্যাখ্যা দেয়, তবে প্রত্যেকে এ সম্পর্কে কিছু জানতে পারে it's
বায়ুআহ

1
এটি আপনাকে দ্রুত একটি আনুমানিক উত্তর দেবে। আপনার যদি সঠিক উত্তর প্রয়োজন হয় তবে আপনার সম্পাদনা select count(*) from table_nameবা অন্য কিছু করা দরকার । dba.stackexchange.com/questions/151769/…
প্রোগ্রামার

@ প্রোগ্রামার্স ধন্যবাদ। প্রায় এক বছর আমাকে অন্ধকারে রেখে যাওয়ার চেয়ে ভাল।
বায়ুআহ

1
@ বেয়াহু আমি নিশ্চিত না যে আপনি আপনার শেষ মন্তব্যে কী বোঝাতে চেয়েছিলেন। আমি কেবল আপনি ধরে নিতে পারি যে আমিই সে আপনার উত্তরটি কম ভোট দিয়েছি, যা আমি নই।
প্রোগ্রামার

1
@ প্রোগ্রামার না, আমি দুঃখিত, আমি এটির অর্থ চাইনি। আমি আপনার ব্যাখ্যার জন্য আপনাকে ধন্যবাদ জানাতে চাইছিলাম, তাই ডাউনভোটার যখন সে / তখন সে করবে তখন আমি কী ভাবতে পেরেছিলাম তা অনুমান করতে পারি।
বায়ুআহ

3

সম্ভবত আপনি একটি করছেন বিবেচনা করতে পারেন SELECT max(Id) - min(Id) + 1। এটি কেবল তখনই কাজ করবে যদি আপনার আইডিগুলি অনুক্রমিক হয় এবং সারিগুলি মোছা না হয়। এটি তবে খুব দ্রুত।


3
সতর্কতা অবলম্বন করুন: সার্ভারগুলি কখনও কখনও অটো ইনক্রিমেন্ট মান> 1 (ব্যাকআপ কারণে) ব্যবহার করে, তাই এই সমাধানটি ভাল তবে আপনাকে প্রথমে আপনার ডিবি কনফিগারেশনটি পরীক্ষা করা উচিত।
অ্যালেক্স

1

EXPLAIN SELECT id FROM ....আমার জন্য কৌশলটি। এবং আমি ফলাফলটির rowsকলামের নীচে সারিগুলির সংখ্যা দেখতে পেয়েছি ।


0

আমি মাঝে মাঝে 60 মিলিয়ন রেকর্ড সহ জার্মান সরকারের পক্ষে সারণীগুলি পরিচালনা করি।

এবং আমাদের মোট সারিতে বহুগুণ জানতে হবে।

সুতরাং আমরা ডাটাবেস প্রোগ্রামাররা সিদ্ধান্ত নিয়েছি যে প্রতিটি টেবিলের মধ্যে সর্বদা একটি রেকর্ড থাকে যাতে মোট রেকর্ড নম্বরগুলি সংরক্ষণ করা হয়। INSERT বা মুছে ফেলা সারিগুলির উপর নির্ভর করে আমরা এই সংখ্যাটি আপডেট করেছি।

আমরা অন্য সমস্ত উপায়ে চেষ্টা করেছি। এটি এখন পর্যন্ত সবচেয়ে দ্রুতগতিতে।


1
এবং কীভাবে আপনি এই সারিটি আপডেট করেছেন তার বিশদ কী? যার অর্থ একটি টেবিলের জন্য ত্রুটিযুক্ত ডিজাইন হলেও, যেখানে সমস্ত সারিটির যাত্রার জন্য আসতে একটি নষ্ট হওয়া প্রয়োজন ted
আঁকুন

5
হ্যাঁ, এটা সত্যিই বোকা হা হা। প্রতিটি প্রশ্নের সাথে আপনাকে প্রথম সারিতে অগ্রাহ্য করতে হবে। আমি কেবল একটি মোট টেবিল তৈরি করব এবং এটি ট্রিগারটির উপর ভিত্তি করে তৈরি করব। ব্যবহারকারী সারণি সন্নিবেশ করান, সর্বমোট সারণী আপডেট করুন। ব্যবহারকারীদের সারণি মুছে ফেলা, মোট টেবিল আপডেট করুন।
এইচটিএমএল গুই

-1

প্রাথমিক কীতে অবস্থিত শর্ত সহ একটি গণনা (*) বিবৃতি আমার জন্য পূর্ণ টেবিল স্ক্যান এড়িয়ে চলা সারি গণনাটি আরও দ্রুত ফিরিয়ে দিয়েছে।

SELECT COUNT(*) FROM ... WHERE <PRIMARY_KEY> IS NOT NULL;

এটি আমার চেয়ে অনেক দ্রুত ছিল

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