ऐसी संरचना पर विचार करें जहां आपके पास दोनों टेबलों पर एक शर्त (जहां, ऑर्डर इत्यादि) के साथ कई से एक (या एक से कई) संबंध हैं। उदाहरण के लिए:क्या क्रॉस-टेबल इंडेक्सिंग संभव है?
CREATE TABLE tableTwo (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
eventTime DATETIME NOT NULL,
INDEX (eventTime)
) ENGINE=InnoDB;
CREATE TABLE tableOne (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
tableTwoId INT UNSIGNED NOT NULL,
objectId INT UNSIGNED NOT NULL,
INDEX (objectID),
FOREIGN KEY (tableTwoId) REFERENCES tableTwo (id)
) ENGINE=InnoDB;
और एक उदाहरण क्वेरी के लिए:
select * from tableOne t1
inner join tableTwo t2 on t1.tableTwoId = t2.id
where objectId = '..'
order by eventTime;
मान लें कि आपको सूचकांक tableOne.objectId
और tableTwo.eventTime
करते हैं। यदि आप उपरोक्त क्वेरी पर व्याख्या करते हैं, तो यह "फाइलों का उपयोग करना" दिखाएगा। अनिवार्य रूप से, यह पहले tableOne.objectId
अनुक्रमणिका लागू करता है, लेकिन यह tableTwo.eventTime
अनुक्रमणिका लागू नहीं कर सकता है क्योंकि यह सूचकांक तालिका की पूरी तरह से है (सीमित परिणाम सेट नहीं), और इस प्रकार इसे मैन्युअल प्रकार करना चाहिए।
इस प्रकार, एक क्रॉस-टेबल इंडेक्स करने का कोई तरीका है, इसलिए प्रत्येक बार परिणाम पुनर्प्राप्त करने के लिए उसे फाइलोर्ट नहीं करना पड़ेगा? कुछ की तरह:
create index ind_t1oi_t2et on tableOne t1
inner join tableTwo t2 on t1.tableTwoId = t2.id
(t1.objectId, t2.eventTime);
इसके अलावा, मैं एक दृश्य और अनुक्रमण कि बनाने में देखा है, लेकिन अनुक्रमण विचारों के लिए समर्थित नहीं है।
क्रॉस-टेबल इंडेक्सिंग संभव नहीं है तो समाधान मैं एक टेबल में सशर्त डेटा को दोहराना संभव नहीं कर रहा हूं। इस मामले में इसका अर्थ है eventTime
tableOne
में दोहराया जाएगा और एक बहु-कॉलम इंडेक्स tableOne.objectId
और tableOne.eventTime
(अनिवार्य रूप से मैन्युअल रूप से इंडेक्स बनाने) पर स्थापित किया जाएगा। हालांकि, मैंने सोचा कि मैं यह देखने के लिए कि क्या यह सबसे अच्छा तरीका था, मैं पहले लोगों के अनुभव की तलाश करूँगा।
बहुत बहुत धन्यवाद!
अपडेट: (
drop procedure if exists populate_table_two;
delimiter #
create procedure populate_table_two(IN numRows int)
begin
declare v_counter int unsigned default 0;
while v_counter < numRows do
insert into tableTwo (eventTime)
values (CURRENT_TIMESTAMP - interval 0 + floor(0 + rand()*1000) minute);
set v_counter=v_counter+1;
end while;
end #
delimiter ;
drop procedure if exists populate_table_one;
delimiter #
create procedure populate_table_one
(IN numRows int, IN maxTableTwoId int, IN maxObjectId int)
begin
declare v_counter int unsigned default 0;
while v_counter < numRows do
insert into tableOne (tableTwoId, objectId)
values (floor(1 +(rand() * maxTableTwoId)),
floor(1 +(rand() * maxObjectId)));
set v_counter=v_counter+1;
end while;
end #
delimiter ;
रूप tableOne
में tableTwo
में 10,000 पंक्तियों और 20,000 पंक्तियों को भरने के लिए इस प्रकार आप इन का उपयोग कर सकते के साथ:
यहाँ लोड हो रहा है परीक्षण डाटा के लिए कुछ प्रक्रियाओं और की तुलना परिणाम हैं tableOne
और यादृच्छिक objectId
एस 1 और 5 के बीच यादृच्छिक संदर्भ), जो मेरे लिए क्रमशः 26.2 और 70.77 सेकेंड लेते हैं:
call populate_table_two(10000);
call populate_table_one(20000, 10000, 5);
अद्यतन 2 (परीक्षण ट्रिगर एसक्यूएल):
नीचे daniHp के ट्रिगर विधि के आधार पर करने की कोशिश की और परीक्षण किया एसक्यूएल है। यह tableOne
पर सिंक में dateTime
रखता है जब tableOne
जोड़ा जाता है या tableTwo
अपडेट किया जाता है। साथ ही, इस विधि को कई से अधिक रिश्तों के लिए भी काम करना चाहिए यदि स्थिति कॉलम को शामिल करने वाली तालिका में कॉपी किया गया हो। tableOne
में 300,000 पंक्तियों के परीक्षण और tableTwo
में 200,000 पंक्तियां, समान सीमा वाले पुरानी क्वेरी की गति 0.12 सेकंड थी और नई क्वेरी की गति अभी भी 0.00 सेकंड के रूप में दिखाई देती है। इस प्रकार, एक स्पष्ट सुधार है, और इस विधि को लाखों पंक्तियों और आगे में अच्छी तरह से प्रदर्शन करना चाहिए।
alter table tableOne add column tableTwo_eventTime datetime;
create index ind_t1_oid_t2et on tableOne (objectId, tableTwo_eventTime);
drop TRIGGER if exists t1_copy_t2_eventTime;
delimiter #
CREATE TRIGGER t1_copy_t2_eventTime
BEFORE INSERT ON tableOne
for each row
begin
set NEW.tableTwo_eventTime = (select eventTime
from tableTwo t2
where t2.id = NEW.tableTwoId);
end #
delimiter ;
drop TRIGGER if exists upd_t1_copy_t2_eventTime;
delimiter #
CREATE TRIGGER upd_t1_copy_t2_eventTime
BEFORE UPDATE ON tableTwo
for each row
begin
update tableOne
set tableTwo_eventTime = NEW.eventTime
where tableTwoId = NEW.id;
end #
delimiter ;
और अद्यतन क्वेरी:
select * from tableOne t1
inner join tableTwo t2 on t1.tableTwoId = t2.id
where t1.objectId = 1
order by t1.tableTwo_eventTime desc limit 0,10;
आप किसी अन्य के लिए एकत्रित तालिका बना सकते हैं। – anttir
@anttir: क्या ऐसा कोई कारण है जो मौजूदा तालिकाओं में से किसी एक में डेटा को दोहराने के लिए बेहतर होगा? – Briguy37
[नमूना कोड] (http://sscce.org/) (यहां, एसक्यूएल के रूप में) विज्ञापन स्कीमा से अधिक उपयोगी है। – outis