การจัดเก็บเส้นทางรถบัสในฐานข้อมูล


16

ฉันได้ทำการวิจัยแล้วและพบว่าฉันควรจัดเก็บเส้นทางตามลำดับจุดแวะพัก สิ่งที่ต้องการ:

Start -> Stop A -> Stop B -> Stop C -> End

ฉันสร้างสามตาราง:

  • เส้นทาง
  • หยุด
  • RouteStops

... โดยที่RouteStopsเป็นตารางจุดแยก

ฉันมีสิ่งที่ชอบ:

เส้นทาง

+---------+
| routeId |
+---------+
|    1    |
+---------+
|    2    |
+---------+

สถานี

+-----------+------+
| stationId | Name |
+-----------+------+
|     1     |   A  |
+-----------+------+
|     2     |   B  |
+-----------+------+
|     3     |   C  |
+-----------+------+
|     4     |   D  |
+-----------+------+

RouteStations

+-------------+---------------+
| routeId(fk) | stationId(fk) |
+-------------+---------------+
|     1       |       A       |
+-------------+---------------+
|     1       |       C       |
+-------------+---------------+
|     1       |       D       |
+-------------+---------------+
|     2       |       A       |
+-------------+---------------+
|     2       |       D       |
+-------------+---------------+

เส้นทางที่ 1 ต้องผ่าน

Station A -> Station C -> Station D

เส้นทางที่ 2 ต้องผ่าน

Station A -> Station D

นี่เป็นวิธีที่ดีในการจัดเก็บเส้นทางหรือไม่

ตามที่Wikipedia :

[... ] ระบบฐานข้อมูลไม่รับประกันการเรียงลำดับของแถวใด ๆ จนกว่าจะมีการORDER BYระบุข้อ [... ]

ฉันสามารถพึ่งพาคีมาฐานข้อมูลเช่นนี้หรืออาจจะต้องทำแตกต่างกันหรือไม่?

นี่เป็นโครงการมหาวิทยาลัยของฉันดังนั้นฉันแค่สงสัยว่าสคีมาดังกล่าวถือได้ว่าถูกต้องหรือไม่ สำหรับกรณีนี้ฉันอาจเก็บเฉพาะหลาย ๆ เส้นทาง (ประมาณ 3-5) และสถานี (ประมาณ 10-15) แต่ละเส้นทางจะมีประมาณ 5 สถานี ฉันก็ยินดีที่จะได้ยินว่าสิ่งนี้ควรมีลักษณะอย่างไรในกรณีของ บริษัท รถโดยสารขนาดใหญ่และของจริง


คุณอาจต้องการที่จะมองไปที่ทั่วไปขนส่งฟีดข้อมูลจำเพาะ ; ในขณะที่ฟีด GTFS ถูกระบุว่าจะแลกเปลี่ยนเป็นไฟล์ CSV แอปพลิเคชันมักจะจัดเก็บและจัดการ GTFS ในฐานข้อมูลเชิงสัมพันธ์
Kurt Raschke

3
คำถามของคุณสลับไปมาระหว่างคำว่า 'หยุด' และ 'สถานี' คุณควรอธิบายคำศัพท์โดเมนของคุณให้ชัดเจน ( เช่นเลือกชื่อและอยู่กับมัน)
Tersosauros

@ monoh_.i มีคำถามประเภทเดียวกันเช่นdba.stackexchange.com/questions/194223/….ถ้าคุณมีความคิดที่คุณสามารถแบ่งปันได้
วิสัยทัศน์

คำตอบ:


19

สำหรับการวิเคราะห์ธุรกิจทั้งหมดที่นำไปสู่สถาปัตยกรรมฐานข้อมูลฉันขอแนะนำให้เขียนกฎ:

  • เส้นทางมี 2 สถานีขึ้นไป
  • สามารถใช้สถานีได้หลายเส้นทาง
  • สถานีบนเส้นทางมาในลำดับที่เฉพาะเจาะจง

กฎข้อที่ 1 และ 2 ตามที่คุณสังเกตเห็นถึงความสัมพันธ์หลายต่อหลายเพื่อให้คุณสรุปได้อย่างถูกต้องในการสร้างเส้นทาง

กฎข้อที่ 3 เป็นกฎที่น่าสนใจ แสดงว่าจำเป็นต้องมีคอลัมน์พิเศษเพื่อให้เหมาะกับความต้องการ มันควรจะไปที่ไหน เราจะเห็นว่าคุณสมบัตินี้ขึ้นอยู่กับเส้นทางและสถานี ดังนั้นจึงควรอยู่ใน routeStations

ฉันจะเพิ่มคอลัมน์ลงในตารางเส้นทาง Stations เรียกว่า "stationOrder"

+-------------+---------------+---------------
| routeId(fk) | stationId(fk) | StationOrder |
+-------------+---------------+---------------
|     1       |       1       |       3      |
+-------------+---------------+---------------
|     1       |       3       |       1      |
+-------------+---------------+---------------
|     1       |       4       |       2      |
+-------------+---------------+---------------
|     2       |       1       |       1      |
+-------------+---------------+---------------
|     2       |       4       |       2      |
+-------------+---------------+---------------

จากนั้นการสืบค้นกลายเป็นเรื่องง่าย:

select rs.routeID,s.Name
from routeStations rs
join
Stations s
on rs.stationId=s.StationId
where rs.routeId=1
order by rs.StationOrder;

+-------------+---------------+
| routeId(fk) | stationId(fk) |
+-------------+---------------+
|     1       |       C       |
+-------------+---------------+
|     1       |       D       |
+-------------+---------------+
|     1       |       A       |
+-------------+---------------+

หมายเหตุ:

  1. ฉันแก้ไข StationId ใน RouteStations ในตัวอย่างของฉัน คุณกำลังใช้ชื่อสถานีเป็นรหัส
  2. หากคุณไม่ได้ใช้ชื่อเส้นทางดังนั้นคุณไม่จำเป็นต้องมีรหัสเส้นทางเลยเพราะคุณสามารถหาได้จากเส้นทางเส้นทาง
  3. แม้ว่าคุณจะเชื่อมโยงไปยังตารางเส้นทางเครื่องมือเพิ่มประสิทธิภาพฐานข้อมูลของคุณจะสังเกตเห็นว่ามันไม่จำเป็นต้องมีลิงก์พิเศษนั้นและเพียงแค่ลบขั้นตอนเพิ่มเติมออกไป

เพื่อพัฒนาในหมายเหตุ 3 ฉันได้สร้างกรณีการใช้งาน:

นี่คือ Oracle 12c Enterprise

โปรดทราบว่าในแผนการดำเนินการด้านล่างนั้นไม่มีการใช้เส้นทางตารางเลย เครื่องมือเพิ่มประสิทธิภาพฐานต้นทุน (CBO) รู้ว่าสามารถรับรหัสประจำตัวได้โดยตรงจากคีย์หลักของ RouteStations (ขั้นตอนที่ 5, INDEX RANGE SCAN บน ROUTESTATIONS_PK, ข้อมูลคำอธิบาย 5 - การเข้าถึง ("RS". "ROUTEID" = 1))

--Table ROUTES
create sequence routeId_Seq start with 1 increment by 1 maxvalue 9999999999999 cache 1000;

CREATE TABLE routes
(
  routeId  INTEGER NOT NULL
);


ALTER TABLE routes ADD (
  CONSTRAINT routes_PK
  PRIMARY KEY
  (routeId)
  ENABLE VALIDATE);

insert into routes values (routeId_Seq.nextval);
insert into routes values (routeId_Seq.nextval);
commit;

--TABLE STATIONS  
create sequence stationId_seq start with 1 increment by 1 maxvalue 9999999999999 cache 1000;

create table stations(
   stationID INTEGER NOT NULL,
   name varchar(50) NOT NULL
);

ALTER TABLE stations ADD (
  CONSTRAINT stations_PK
  PRIMARY KEY
  (stationId)
  ENABLE VALIDATE);

insert into stations values (stationId_seq.nextval,'A');
insert into stations values (stationId_seq.nextval,'B');
insert into stations values (stationId_seq.nextval,'C');
insert into stations values (stationId_seq.nextval,'D');
commit;
--

--Table ROUTESTATIONS 
CREATE TABLE routeStations
(
  routeId       INTEGER NOT NULL,
  stationId     INTEGER NOT NULL,
  stationOrder  INTEGER NOT NULL
);


ALTER TABLE routeStations ADD (
  CONSTRAINT routeStations_PK
  PRIMARY KEY
  (routeId, stationId)
  ENABLE VALIDATE);

ALTER TABLE routeStations ADD (
  FOREIGN KEY (routeId) 
  REFERENCES ROUTES (ROUTEID)
  ENABLE VALIDATE,
  FOREIGN KEY (stationId) 
  REFERENCES STATIONS (stationId)
  ENABLE VALIDATE);

insert into routeStations values (1,1,3);
insert into routeStations values (1,3,1);
insert into routeStations values (1,4,2);
insert into routeStations values (2,1,1);
insert into routeStations values (2,4,2);
commit;

explain plan for select rs.routeID,s.Name
from ndefontenay.routeStations rs
join
ndefontenay.routes r
on r.routeId=rs.routeId
join ndefontenay.stations s
on rs.stationId=s.stationId
where rs.routeId=1
order by rs.StationOrder;

set linesize 1000
set pages 500
select * from table (dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2617709240                                                                                                                                                                                                                                                                                 

---------------------------------------------------------------------------------------------------                                                                                                                                                                                                         
| Id  | Operation                      | Name             | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                         
---------------------------------------------------------------------------------------------------                                                                                                                                                                                                         
|   0 | SELECT STATEMENT               |                  |     1 |    79 |     1 (100)| 00:00:01 |                                                                                                                                                                                                         
|   1 |  SORT ORDER BY                 |                  |     1 |    79 |     1 (100)| 00:00:01 |                                                                                                                                                                                                         
|   2 |   NESTED LOOPS                 |                  |       |       |            |          |                                                                                                                                                                                                         
|   3 |    NESTED LOOPS                |                  |     1 |    79 |     0   (0)| 00:00:01 |                                                                                                                                                                                                         
|   4 |     TABLE ACCESS BY INDEX ROWID| ROUTESTATIONS    |     1 |    39 |     0   (0)| 00:00:01 |                                                                                                                                                                                                         
|*  5 |      INDEX RANGE SCAN          | ROUTESTATIONS_PK |     1 |       |     0   (0)| 00:00:01 |                                                                                                                                                                                                         
|*  6 |     INDEX UNIQUE SCAN          | STATIONS_PK      |     1 |       |     0   (0)| 00:00:01 |                                                                                                                                                                                                         
|   7 |    TABLE ACCESS BY INDEX ROWID | STATIONS         |     1 |    40 |     0   (0)| 00:00:01 |                                                                                                                                                                                                         
---------------------------------------------------------------------------------------------------                                                                                                                                                                                                         

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                         
---------------------------------------------------                                                                                                                                                                                                                                                         

   5 - access("RS"."ROUTEID"=1)                                                                                                                                                                                                                                                                             
   6 - access("RS"."STATIONID"="S"."STATIONID")

ตอนนี้ความสนุกมาเพิ่มชื่อคอลัมน์ในตารางเส้นทาง ตอนนี้มีคอลัมน์ที่เราต้องการใน "เส้นทาง" จริง ๆ แล้ว CBO ใช้ดัชนีเพื่อค้นหา rowID สำหรับเส้นทาง 1 จากนั้นเข้าถึงตาราง (การเข้าถึงตารางโดยดัชนี rowid) และคว้าคอลัมน์ "route.name"

ALTER TABLE ROUTES
 ADD (name  VARCHAR2(50));

update routes set name='Old Town' where routeId=1;
update routes set name='North County' where routeId=2;
commit;

explain plan for select r.name as routeName,s.Name as stationName
from routeStations rs
join
routes r
on r.routeId=rs.routeId
join stations s
on rs.stationId=s.stationId
where rs.routeId=1
order by rs.StationOrder;

set linesize 500
set pages 500
select * from table (dbms_xplan.display);

PLAN_TABLE_OUTPUT                                                                                                                                                                                                                                                                                           
---------------------------------------------------------------------------------------------------
Plan hash value: 3368128430                                                                                                                                                                                                                                                                                 

----------------------------------------------------------------------------------------------------                                                                                                                                                                                                        
| Id  | Operation                       | Name             | Rows  | Bytes | Cost (%CPU)| Time     |                                                                                                                                                                                                        
----------------------------------------------------------------------------------------------------                                                                                                                                                                                                        
|   0 | SELECT STATEMENT                |                  |     1 |   119 |     1 (100)| 00:00:01 |                                                                                                                                                                                                        
|   1 |  SORT ORDER BY                  |                  |     1 |   119 |     1 (100)| 00:00:01 |                                                                                                                                                                                                        
|   2 |   NESTED LOOPS                  |                  |       |       |            |          |                                                                                                                                                                                                        
|   3 |    NESTED LOOPS                 |                  |     1 |   119 |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
|   4 |     NESTED LOOPS                |                  |     1 |    79 |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
|   5 |      TABLE ACCESS BY INDEX ROWID| ROUTES           |     1 |    40 |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
|*  6 |       INDEX UNIQUE SCAN         | ROUTES_PK        |     1 |       |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
|   7 |      TABLE ACCESS BY INDEX ROWID| ROUTESTATIONS    |     1 |    39 |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
|*  8 |       INDEX RANGE SCAN          | ROUTESTATIONS_PK |     1 |       |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
|*  9 |     INDEX UNIQUE SCAN           | STATIONS_PK      |     1 |       |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
|  10 |    TABLE ACCESS BY INDEX ROWID  | STATIONS         |     1 |    40 |     0   (0)| 00:00:01 |                                                                                                                                                                                                        
----------------------------------------------------------------------------------------------------                                                                                                                                                                                                        

Predicate Information (identified by operation id):                                                                                                                                                                                                                                                         
---------------------------------------------------                                                                                                                                                                                                                                                         

   6 - access("R"."ROUTEID"=1)                                                                                                                                                                                                                                                                              
   8 - access("RS"."ROUTEID"=1)                                                                                                                                                                                                                                                                             
   9 - access("RS"."STATIONID"="S"."STATIONID")      

@ Nicolas.i มีคำถามแบบเดียวกันคุณสามารถช่วยฉันdba.stackexchange.com/questions/194223/…
vision

3

คุณถูกต้องไม่มีลำดับของเร็กคอร์ดในตารางเชิงสัมพันธ์ ซึ่งหมายความว่าคุณต้องระบุวิธีการสั่งซื้อสถานีอย่างชัดเจนในแต่ละเส้นทาง

ขึ้นอยู่กับว่าคุณวางแผนจะเข้าถึงข้อมูลที่คุณทำได้

  1. เพิ่มsequenceNumberคอลัมน์ลงในRouteStationsในการจัดเก็บอย่างชัดเจนตามลำดับของแต่ละสถานีในแต่ละเส้นทาง
  2. เพิ่มnextStationIdคอลัมน์เพื่อจัดเก็บ "ตัวชี้" ไปยังสถานีถัดไปในแต่ละเส้นทาง

@ mustaccio.i มีคำถามแบบเดียวกันคุณสามารถช่วยฉันdba.stackexchange.com/questions/194223/…
vision

0

ฉันไม่เห็นใครพูดอะไรเกี่ยวกับเรื่องนี้ดังนั้นฉันจึงคิดว่าฉันจะเพิ่มเกรดของคุณ ฉันยังวางดัชนีเฉพาะที่ไม่ได้ทำคลัสเตอร์ (ขึ้นอยู่กับ RDBMS ของคุณ) ในตาราง RouteStations / RouteStops ในทั้งสามคอลัมน์ ด้วยวิธีนี้คุณจะไม่สามารถทำผิดพลาดและมีรถบัสไปยังสถานีถัดไป 2 แห่ง สิ่งนี้จะทำให้การอัปเดตยากขึ้น แต่ฉันคิดว่าควรพิจารณาว่าเป็นส่วนหนึ่งของการออกแบบที่ดี


-1

ฉันกำลังพูดเป็นโปรแกรมเมอร์แอปพลิเคชัน :

อย่าคิดว่าจะทำการกำหนดเส้นทางหรือกำหนดเวลาด้วยแบบสอบถามกับฐานข้อมูล (หรือใน proc ที่เก็บไว้) มันจะไม่เร็วพอ ( ยกเว้นกรณีนี้เป็นเพียงปัญหา "การบ้าน" )

แม้แต่แอปพลิเคชันที่ประมวลผลข้อมูลในหน่วยความจำที่กำลังโหลดข้อมูลจากฐานข้อมูลจะไม่รวดเร็วเว้นแต่ข้อมูลทั้งหมดจะถูกโหลดเมื่อเริ่มต้นระบบหรือข้อมูลถูกเก็บไว้ในรูปแบบที่ถูกลดทอน เมื่อข้อมูลถูกทำให้เสื่อมเสียแล้วมีจุดเล็กน้อยในการใช้ฐานข้อมูลเชิงสัมพันธ์

ดังนั้นฉันคิดว่าฐานข้อมูลเป็นสำเนาของข้อมูลและยอมรับว่าฉันจะต้องเก็บไว้ล่วงหน้าในหน่วยความจำแอปพลิเคชันหรือในเซิร์ฟเวอร์ cashing เช่น membase

คำตอบของ ndefontenay ให้การออกแบบตารางที่ดีเป็นจุดเริ่มต้น แต่คุณต้องพิจารณาว่าเส้นทางมีช่วงเวลาที่แตกต่างกันขึ้นอยู่กับช่วงเวลาของวันและมักจะมีจุดหยุดที่แตกต่างกันตามเวลาวันในสัปดาห์หรือแม้กระทั่งวันหยุดโรงเรียน


5
เขาไม่มีที่พูดถึงว่าเขาต้องการกำหนดเส้นทางหรือกำหนดตารางเวลา เขาถามวิธีเก็บเส้นทางในฐานข้อมูล นอกจากนี้ในขณะที่โปรแกรมเมอร์อาจถูกขวัญเสียผมหวังว่าข้อมูลจะถูกทำให้เป็นมาตรฐานในบางจุด :)
AnoE
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.