Lưu trữ các tuyến xe buýt trong cơ sở dữ liệu


16

Tôi đã thực hiện một số nghiên cứu và thấy rằng tôi nên lưu trữ một tuyến đường như một chuỗi các điểm dừng. Cái gì đó như:

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

Tôi đã tạo ba bảng:

  • Tuyến đường
  • Dừng lại
  • Tuyến đường

... Trong đó RouteStops là một bảng nối.

Tôi có một cái gì đó như:

Tuyến đường

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

Trạm

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

Tuyến đường

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

Tuyến 1 đi qua

Station A -> Station C -> Station D

Tuyến 2 đi qua

Station A -> Station D

Đây có phải là một cách tốt để lưu trữ các tuyến đường?

Theo Wikipedia :

[...] hệ thống cơ sở dữ liệu không đảm bảo bất kỳ thứ tự nào của các hàng trừ khi một ORDER BYmệnh đề được chỉ định [...]

Tôi có thể dựa vào một lược đồ cơ sở dữ liệu như vậy hoặc có thể điều này nên được thực hiện khác nhau?

Đây thực sự là dự án đại học của tôi, vì vậy tôi chỉ tự hỏi liệu lược đồ đó có thể được coi là một chính xác hay không. Trong trường hợp này, tôi có thể chỉ lưu trữ một số tuyến (khoảng 3-5) và các trạm (khoảng 10-15), mỗi tuyến sẽ bao gồm khoảng 5 trạm. Tôi cũng sẽ rất vui khi nghe điều này sẽ như thế nào trong trường hợp của công ty xe buýt thực sự và lớn.


Bạn có thể muốn xem Đặc điểm kỹ thuật của thức ăn quá cảnh chung ; trong khi nguồn cấp GTFS được chỉ định để được trao đổi dưới dạng tệp CSV, các ứng dụng thường lưu trữ và thao tác GTFS trong cơ sở dữ liệu quan hệ.
Kurt Raschke

3
Câu hỏi của bạn chuyển giữa các cụm từ 'Dừng lại' và 'Trạm'. Bạn có thể nên làm rõ từ vựng tên miền của bạn ( tức là chọn một tên và ở lại với nó).
Tersizardos 11/03/2016

@ monoh_.i có loại cũng tương tự như câu hỏi dba.stackexchange.com/questions/194223/... .Nếu bạn có ý tưởng bạn có thể chia sẻ
tầm nhìn

Câu trả lời:


19

Đối với tất cả các phân tích kinh doanh dẫn đến kiến ​​trúc cơ sở dữ liệu, tôi khuyên bạn nên viết quy tắc:

  • Một tuyến đường có 2 trạm trở lên
  • Một trạm có thể được sử dụng bởi nhiều tuyến đường
  • Các trạm trên một tuyến đường theo thứ tự cụ thể

Các quy tắc thứ 1 và thứ 2 như bạn nhận thấy ngụ ý rất nhiều mối quan hệ, do đó bạn đã kết luận chính xác để tạo routeStations.

Quy tắc thứ 3 là quy tắc thú vị. Nó ngụ ý rằng một cột thêm là cần thiết để phù hợp với yêu cầu. Nó nên đi đâu? Chúng ta có thể thấy rằng khách sạn này phụ thuộc vào Tuyến VÀ Trạm. Do đó, nó nên được đặt trong routeStations.

Tôi sẽ thêm một cột vào bảng RouteStations được gọi là "trạm".

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

Sau đó, truy vấn trở nên dễ dàng:

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       |
+-------------+---------------+

Ghi chú:

  1. Tôi đã sửa lỗi StationId trong RouteStations trong ví dụ của mình. Bạn đang sử dụng StationName làm Id.
  2. Nếu bạn không sử dụng tên tuyến đường, thì thậm chí không cần tuyến đường vì bạn có thể lấy tên đó từ routeStations
  3. Ngay cả khi bạn sẽ liên kết với bảng lộ trình, trình tối ưu hóa cơ sở dữ liệu của bạn sẽ nhận thấy rằng nó không cần liên kết bổ sung đó và chỉ cần loại bỏ các bước bổ sung.

Để phát triển trên lưu ý 3, tôi đã xây dựng trường hợp sử dụng:

Đây là doanh nghiệp Oracle 12c.

Lưu ý rằng trong kế hoạch thực hiện bên dưới, các tuyến bảng không được sử dụng. Trình tối ưu hóa cơ sở chi phí (CBO) biết rằng nó có thể lấy tuyếnId trực tiếp từ khóa chính của routeStations (bước 5, INDEX RANGE SCAN trên ROUTESTATION_PK, Thông tin dự đoán 5 - quyền truy cập ("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")

Bây giờ là phần thú vị, hãy thêm một tên cột vào bảng tuyến đường. Bây giờ có một cột chúng ta thực sự cần trong "tuyến đường". CBO sử dụng chỉ mục để tìm rowID cho tuyến 1, sau đó truy cập vào bảng (truy cập bảng theo chỉ mục rowid) và lấy cột "Rout.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 có loại cũng tương tự như các câu hỏi mà bạn có thể giúp tôi dba.stackexchange.com/questions/194223/...
tầm nhìn

3

Bạn đã đúng, không có thứ tự hồ sơ vốn có trong một bảng quan hệ. Điều này có nghĩa là bạn cần cung cấp một số cách đặt hàng rõ ràng cho các trạm trong mỗi tuyến.

Tùy thuộc vào cách bạn dự định truy cập dữ liệu bạn có thể

  1. Thêm sequenceNumbercột để RouteStationslưu trữ, rõ ràng, trình tự của mỗi trạm trong mỗi tuyến.
  2. Thêm nextStationIdcột để lưu trữ "con trỏ" đến trạm tiếp theo trong mỗi tuyến.

@ mustaccio.i có loại cũng tương tự như các câu hỏi mà bạn có thể giúp tôi dba.stackexchange.com/questions/194223/...
tầm nhìn

0

Tôi đã không thấy bất cứ ai nói bất cứ điều gì về điều này vì vậy tôi nghĩ rằng tôi sẽ thêm cho lớp của bạn. Tôi cũng sẽ đặt một chỉ mục duy nhất không được phân cụm (tùy thuộc vào RDBMS của bạn) trên bảng RouteStations / RouteStops trên tất cả ba cột. Bằng cách này, bạn sẽ không thể phạm sai lầm và đưa xe buýt đi đến 2 trạm tiếp theo. Điều này sẽ làm cho việc cập nhật khó khăn hơn nhưng tôi nghĩ vẫn nên được coi là một phần của một thiết kế tốt.


-1

Tôi đang nói như một lập trình viên ứng dụng :

Thậm chí đừng nghĩ đến việc thực hiện định tuyến hoặc định thời gian với các truy vấn đối với cơ sở dữ liệu (hoặc trong một lưu trữ được lưu trữ), nó sẽ không bao giờ đủ nhanh. ( Trừ khi đây chỉ là vấn đề về bài tập về nhà của người Viking. )

Ngay cả đối với một ứng dụng xử lý dữ liệu trong bộ nhớ tải dữ liệu từ cơ sở dữ liệu sẽ không bao giờ nhanh trừ khi tất cả dữ liệu được tải khi khởi động hoặc dữ liệu được lưu trữ ở dạng khử. Một khi dữ liệu bị mất tinh thần, có rất ít điểm trong việc sử dụng cơ sở dữ liệu quan hệ.

Do đó, tôi sẽ nghĩ rằng cơ sở dữ liệu là bản sao dữ liệu của Master master và chấp nhận rằng tôi cũng sẽ phải lưu trữ nó được xử lý trước trong bộ nhớ ứng dụng hoặc trong một máy chủ rút tiền như membase.

Câu trả lời của ndefontenay đưa ra một thiết kế bảng tốt làm điểm khởi đầu, nhưng bạn phải xem xét rằng các tuyến đường có thời gian khác nhau tùy thuộc vào thời gian trong ngày và thường có các điểm dừng khác nhau tùy thuộc vào thời gian, ngày trong tuần hoặc thậm chí là ngày nghỉ của trường.


5
Không nơi nào anh ta đề cập rằng anh ta muốn thực hiện định tuyến hoặc thời gian biểu; anh ta hỏi làm thế nào để lưu trữ các tuyến đường trong một DB. Ngoài ra, trong khi một lập trình viên có thể bị mất tinh thần, tôi chắc chắn hy vọng dữ liệu sẽ được ( bình thường hóa ) tại một số điểm. :)
AnoE 11/03/2016
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.