Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

उस क्वेरी को ऑप्टिमाइज़ करें जो सम्मिलित तालिका से किसी फ़ील्ड द्वारा परिणामित होती है

समस्या यह है कि name . के आधार पर समूहीकरण किया जाता है आपको sales_id खो देता है जानकारी, इसलिए MySQL को एक अस्थायी तालिका का उपयोग करने के लिए मजबूर किया जाता है।

हालांकि यह सबसे साफ समाधान नहीं है, और मेरे कम पसंदीदा तरीकों में से एक है, आप दोनों पर एक नई अनुक्रमणिका जोड़ सकते हैं name और sales_id कॉलम, जैसे:

ALTER TABLE `yourdb`.`ycs_products` 
ADD INDEX `name_sales_id_idx` (`name` ASC, `sales_id` ASC);

और बल force index . के साथ इस अनुक्रमणिका का उपयोग करने के लिए क्वेरी या use index :

SELECT SQL_NO_CACHE p.name, COUNT(1) FROM ycs_sales s
INNER JOIN ycs_products p use index(name_sales_id_idx) ON s.id = p.sales_id 
WHERE s.dtm BETWEEN '2018-02-16 00:00:00' AND  '2018-02-22 23:59:59'
GROUP BY p.name;

मेरे निष्पादन ने तालिका पी पर केवल "कहां का उपयोग करना; अनुक्रमणिका का उपयोग करना" और तालिका एस पर "कहां का उपयोग करना" रिपोर्ट किया।

वैसे भी, मैं आपको अपने स्कीमा के बारे में फिर से सोचने का दृढ़ता से सुझाव देता हूं, क्योंकि शायद आपको इन दो तालिकाओं के लिए कुछ बेहतर डिज़ाइन मिल सकता है। दूसरी ओर, यदि यह आपके आवेदन का महत्वपूर्ण हिस्सा नहीं है, तो आप "मजबूर" सूचकांक से निपट सकते हैं।

संपादित करें

चूंकि यह बिल्कुल स्पष्ट है कि समस्या डिजाइन में है, मैं कई-से-अनेक के रूप में संबंधों को चित्रित करने का सुझाव देता हूं। यदि आपके पास इसे अपने परीक्षण परिवेश में सत्यापित करने का अवसर है, तो मैं यहां क्या करूंगा:

1) केवल उत्पाद का नाम और आईडी स्टोर करने के लिए एक अस्थायी तालिका बनाएं:

create temporary table tmp_prods
select min(id) id, name
from ycs_products
group by name;

2) अस्थायी तालिका से शुरू करके, ycs_product . के लिए एक प्रतिस्थापन बनाने के लिए बिक्री तालिका में शामिल हों :

create table ycs_products_new
select * from tmp_prods;

ALTER TABLE `poc`.`ycs_products_new` 
CHANGE COLUMN `id` `id` INT(11) NOT NULL ,
ADD PRIMARY KEY (`id`);

3) जॉइन टेबल बनाएं:

CREATE TABLE `prod_sale` (
`prod_id` INT(11) NOT NULL,
`sale_id` INT(11) NOT NULL,
PRIMARY KEY (`prod_id`, `sale_id`),
INDEX `sale_fk_idx` (`sale_id` ASC),
CONSTRAINT `prod_fk`
  FOREIGN KEY (`prod_id`)
  REFERENCES ycs_products_new (`id`)
  ON DELETE NO ACTION
  ON UPDATE NO ACTION,
CONSTRAINT `sale_fk`
  FOREIGN KEY (`sale_id`)
  REFERENCES ycs_sales (`id`)
  ON DELETE NO ACTION
  ON UPDATE NO ACTION);

और इसे मौजूदा मानों से भरें:

insert into prod_sale (prod_id, sale_id)
select tmp_prods.id, sales_id from ycs_sales s
inner join ycs_products p
on p.sales_id=s.id
inner join tmp_prods on tmp_prods.name=p.name;

अंत में, शामिल हों क्वेरी:

select name, count(name) from ycs_products_new p
inner join prod_sale ps on ps.prod_id=p.id
inner join ycs_sales s on s.id=ps.sale_id 
WHERE s.dtm BETWEEN '2018-02-16 00:00:00' AND  '2018-02-22 23:59:59'
group by p.id;

कृपया, ध्यान दें कि द्वारा समूह प्राथमिक कुंजी पर है, नाम नहीं।

आउटपुट की व्याख्या करें:

explain select name, count(name) from ycs_products_new p inner join prod_sale ps on ps.prod_id=p.id inner join ycs_sales s on s.id=ps.sale_id  WHERE s.dtm BETWEEN '2018-02-16 00:00:00' AND  '2018-02-22 23:59:59' group by p.id;
+------+-------------+-------+--------+---------------------+---------+---------+-----------------+------+-------------+
| id   | select_type | table | type   | possible_keys       | key     | key_len | ref             | rows | Extra       |
+------+-------------+-------+--------+---------------------+---------+---------+-----------------+------+-------------+
|    1 | SIMPLE      | p     | index  | PRIMARY             | PRIMARY | 4       | NULL            |    3 |             |
|    1 | SIMPLE      | ps    | ref    | PRIMARY,sale_fk_idx | PRIMARY | 4       | test.p.id       |    1 | Using index |
|    1 | SIMPLE      | s     | eq_ref | PRIMARY,dtm         | PRIMARY | 4       | test.ps.sale_id |    1 | Using where |
+------+-------------+-------+--------+---------------------+---------+---------+-----------------+------+-------------+


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. विशिष्ट फ़ील्ड मान प्रति यादृच्छिक पंक्ति का चयन करें?

  2. डीबी स्कीमा परिवर्तनों को ट्रैक करने के लिए तंत्र

  3. एकाधिक मानों से मेल खाने वाले रिकॉर्ड का समूह खोजें

  4. DatabaseMetaData का उपयोग करके mysql तालिका टिप्पणी प्राप्त करें

  5. mysql हटाएँ, autoincrement