Bazy Danych II. Ćwiczenia Bartosz Zieliński 16 kwietnia 2011
Spis treści 1 Powtórzenie SQL 3 1.1 Tworzenie i usuwanie tabel........................ 3 1.2 Wstawianie danych do tabel........................ 4 1.3 Usuwanie wierszy z tabel......................... 5 1.4 Modyfikacja danych w tabelach...................... 5 1.5 Zapytania SELECT............................. 5 1.5.1 Proste zapytania SELECT...................... 5 1.5.2 Złączenia............................... 5 1.5.3 Zapytania z grupowaniem..................... 5 1.5.4 Podzapytania............................. 5 2 Elementarny OLAP w SQL 6 2.1 Przykładowy schemat typu gwiazda................... 6 2.2 Przykładowe zapytania z ROLLUP i CUBE................ 9 3 Optymalizacja zapytań 11 3.1 Tworzenie indeksów............................ 11 3.2 Korzystanie z EXPLAIN PLAN....................... 13 3.3 Zbieranie statystyk............................. 14 2
1 Powtórzenie SQL 1.1 Tworzenie i usuwanie tabel Tabele tworzymy poleceniem CREATE TABLE którego argumentami są nazwa tabeli i lista par (nazwa kolumny, typ kolumny). Przykład: CREATE TABLE "EMPLOYEES" ( "EMPLOYEE_ID" NUMBER(6,0) PRIMARY KEY, "FIRST_NAME" VARCHAR2(20 BYTE), "LAST_NAME" VARCHAR2(25 BYTE), "EMAIL" VARCHAR2(25 BYTE), "PHONE_NUMBER" VARCHAR2(20 BYTE), "HIRE_DATE" DATE, "JOB_ID" VARCHAR2(10 BYTE), "SALARY" NUMBER(8,2), "COMMISSION_PCT" NUMBER(2,2), "MANAGER_ID" NUMBER(6,0), "DEPARTMENT_ID" NUMBER(4,0) ); Identyfikatorów kolumn nie trzeba ujmować w cudzysłowy gdy nie zawierają spacji ani zakazanych znaków. PRIMARY KEY w pierwszym wierszu oznacza że wartość w tej kolumnie jest kluczem głṕownym, tzn. jednoznacznie identyfikuje wiersz w tabeli. 3
Rozdział 1 Powtórzenie SQL Identyfikator VARCHAR2 1 oznacza typ tekstowy (łańcuch znaków). Liczba w nawiasie oznacza maksymalny rozmiar napisu (napis może być krótszy ale nie dłuższy). Tabelę można usunąć poleceniem DROP TABLE którego argumentem jest nazwa tabeli: drop table employees; 1.2 Wstawianie danych do tabel Do wstawiania nowych wierszy służy instrukcja INSERT. Przykłd: insert into employees(employee_id, first_name, last_name) values(1000, Donnie, Darko ); Jak widać po nazwie tabeli (tu: employees) umieszczamy listę kolumn (nie muszą to być wszystkie kolumny tabeli), a po słowie kluczowym VALUES listę wartości w dokładnie takiej kolejności jak na pierwszej liście. W pominiętych kolumnach zostaną umieszczone wartości NULL (które oznaczają brak wartości). Uwaga: kolumna oznaczona jako PRIMARY KEY nie może być NULL. Jeśli pominiemy listę kolumn po nazwie tabeli musimy po słowie kluczowym VALUES umieścić listę wartości odpowiadających wszystkim kolumnom w takiej kolejności w jakiej kolumny te pojawiają się w CREATE TABLE. Zamiast wstawiać po jednym wierszu można wstawić hurtem większą ich ilość używając zapytania SELECT jako źródła danych: insert into employees select * from hr.employees; Nazwy tabel znajdujących się w innym schemacie niż bieżący schemat użytkownika należy poprzedzać nazwą schematu i kropką. Np. Powyżej wstawiliśmy do tabeli employees w naszym schemacie dane z tabeli employees w schemacie HR. 1 To typ występujący tylko w dialekcie SQL bazy Oracle. We wszystkich innych ten typ nazywa się VARCHAR. 4
Rozdział 1 Powtórzenie SQL Aby zastać wstawione lub zmodyfikowane dane po wylogowaniu się z bazy i ponownym do niej zalogowaniu należy pamieętać o wydaniu polecenia COMMIT zatwierdzającego bieżącą transakcję. 1.3 Usuwanie wierszy z tabel Do usuwania wierszy z tabel służy polecenie DELETE. Np. aby usunąć z tabeli employees wiersze zawierające dane o pracownikach których pensja jest mniejsza niż 100 należy wydać polecenie delete from employees where salary<100; 1.4 Modyfikacja danych w tabelach Do modyfikowania danych w tabelach służy polecenie UPDATE. Nstępujące polecenie zwiększa pensje o 100 wszystkim tym pracownikom z tabeli employees których pensja nie przekracza 1000: update employees set salary = salary+100 where salary<1000; 1.5 Zapytania SELECT 1.5.1 Proste zapytania SELECT 1.5.2 Złączenia 1.5.3 Zapytania z grupowaniem 1.5.4 Podzapytania 5
Elementarny OLAP w SQL 2 2.1 Przykładowy schemat typu gwiazda Nasz przykładowy schemat będzie składał się z trzech tabel: DIM_LOCATIONS opisującej lokalizacje punktów sprzedaży, DIM_PRODUCTS opisującej produkty, SELLS_FACTS opisującej fakty sprzedaży. Tabele DIM_LOCATIONS i DIM_PRODUCTS będą pełniły rolę tabel wymiarów a tabela SELLS_FACTS tabeli faktów. 1. Zaczynamy od utworzenia tabeli DIM_LOCATIONS kradnąc dane z odpowiednich tabel ze schematu HR. Należy zwrócić uwagę na to że otrzymana tabela jest zdenormalizowana a także na sposób w jaki została otrzymana kolumna lid s konkatenacji kluczy głównych tabel hr.locations, hr.countries i hr.regions: create table dim_locations as select to_char(r.region_id) c.country_id to_char(l.location_id) lid, c.country_id, r.region_name, c.country_name, l.street_address, l.postal_code, l.city, l.state_province 6
Rozdział 2 Elementarny OLAP w SQL from (hr.locations l full outer join hr.countries c on l.country_id=c.country_id) full outer join hr.regions r on c.region_id= r.region_id; Wygenerowana tabela ma typy kolumn odpowiednie do danych którymi została wypełniona, niestety klucz główny trzeba utworzyć samemu: alter table dim_locations add primary key(lid); 2. Następnym krokiem jest utworzenie tabeli DIM_PRODUCTS: create table dim_products ( pid integer primary key, brand varchar(50), color varchar(50), price number(8,2) ); i wypełnienie jej danymi: declare begin insert into dim_products values(1, brand_a, black,1000); insert into dim_products values(2, brand_a, red,1000); insert into dim_products values(3, brand_b, black,2000); insert into dim_products values(4, brand_b, red,2000); insert into dim_products values(5, brand_c, black,1500); insert into dim_products values(6, brand_c, red,1500); 7
Rozdział 2 Elementarny OLAP w SQL commit; end; 3. Na koniec tworzymy tabelę faktów z kluczami obcymi do tabel wymiarów ( należy zwrócić uwageę że czas jest tu także wymiarem, ale przechowywanym w całości w kolumnie d tabeli SELLS_FACTS): create table sells_facts ( fid integer primary key, pid integer references dim_products(pid), lid VARCHAR2(82 BYTE) references dim_locations(lid), d date not null, n integer, val number(8,2) not null ); i wypełniamy ją przypadkowymi danymi: declare type lids_t is varray(100) of varchar2(82 byte); x lids_t:=lids_t(); p integer; v number(8,2); nn integer; dd date; loc varchar2(82 byte); begin select lid bulk collect into x from dim_locations; for i in 1..500 loop p:=ceil(5*dbms_random.value); select price into v from dim_products where pid=p; nn:=floor(10*dbms_random.value); dd:=to_date(to_char(ceil(27*dbms_random.value)) - to_char(ceil(12*dbms_random.value)) -2010, DD-MM-YYYY ); 8
Rozdział 2 Elementarny OLAP w SQL loc:=x(ceil((x.count-1)*dbms_random.value)); insert into sells_facts values(i,p,loc,dd,nn,nn*v); end loop; commit; end; 2.2 Przykładowe zapytania z ROLLUP i CUBE Wypróbować następujące zapytania: select sum(s.n),sum(s.val), p.brand, p.color from sells_facts s inner join dim_products p on p.pid= s.pid group by rollup(p.brand, p.color); -------------------------------------------- select sum(s.n),sum(s.val), p.brand, p.color, grouping(p.color),grouping(p.brand) from sells_facts s inner join dim_products p on p.pid= s.pid group by rollup(p.brand, p.color); -------------------------------------------- select sum(s.n),sum(s.val), p.brand, p.color, grouping(p.color),grouping(p.brand), grouping_id(p.brand, p.color) from sells_facts s inner join dim_products p on p.pid= s.pid group by rollup(p.brand, p.color); -------------------------------------------- 9
Rozdział 2 Elementarny OLAP w SQL select sum(s.n),sum(s.val), p.brand, p.color, extract(month from s.d), grouping(p.color),grouping(p.brand), grouping_id(p.brand, p.color) from (sells_facts s inner join dim_products p on p.pid= s.pid) inner join dim_locations l on l.lid= s.lid group by grouping sets(extract(month from s.d), rollup(p.brand,p.color)); 10
3 Optymalizacja zapytań 3.1 Tworzenie indeksów 1. Utworzyć tabele o nazwach employees i employees2 będące kopiami tabeli HR.EMPLOYEES przy użyciu polecenia create table employees as select * from hr.employees; i podobnie w przypadku tabeli employees2. 2. Podobnie utworzyć kopię o nazwie departments tabeli departments. 3. Utworzyć indeks na kolumnie EMPLOYEE_ID w tabeli EMPLOYEE2. używając polecenia CREATE INDEX empl_index ON employees2(employee_id); 4. Utworzyć indeks na kolumnie DEPARTMENT_ID w tabeli DEPARTMENTS: CREATE INDEX dept_index ON departments(department_id); 5. Utworzyć indeks na kolumnach LAST_NAME i FIRST_NAME jednocześnie w tabelach employees i employees2. Przykład: 11
Rozdział 3 Optymalizacja zapytań CREATE INDEX names_index ON employees2(last_name,first_name); 6. Dodać do tabeli employees2 500 dodatkowych kopii tabeli hr.employees używając natępującego bloku PLSQL: declare begin for i in 1..500 loop insert into employees2 select * from hr.employees; end loop; commit; end; 7. Utworzyć klaster o nazwie empl_and_dept na kolumnie DEPARTMENT_ID używając polecenia: create cluster empl_and_dept (DEPARTMENT_ID NUMBER(4,0)); 8. Utworzyć indeks na klastrze empl_and_dept: CREATE INDEX empl_and_dept_index ON CLUSTER empl_and_dept; 9. Utworzyć tabele departments3 i employees3 w klastrze: CREATE TABLE "HYBRYDOWE"."DEPARTMENTS3" ( "DEPARTMENT_ID" NUMBER(4,0), "DEPARTMENT_NAME" VARCHAR2(30 BYTE) NOT NULL ENABLE, "MANAGER_ID" NUMBER(6,0), "LOCATION_ID" NUMBER(4,0) )cluster empl_and_dept(department_id); 12
Rozdział 3 Optymalizacja zapytań and similarily for the other table. 10. Skopiować do powyższych tabel dane z tabel departments i employees2. 3.2 Korzystanie z EXPLAIN PLAN 1. Utworzyć tablicę dla EXPLAIN PLAN: create table PLAN_TABLE ( statement_id plan_id timestamp remarks operation options object_node object_owner object_name object_alias object_instance object_type optimizer search_columns id parent_id depth position cost cardinality bytes other_tag partition_start partition_stop partition_id other distribution varchar2(30), number, date, varchar2(4000), varchar2(30), varchar2(255), varchar2(128), varchar2(30), varchar2(30), varchar2(65), varchar2(30), varchar2(255), number, varchar2(255), varchar2(255), varchar2(255), long, varchar2(30), 13
Rozdział 3 Optymalizacja zapytań ); cpu_cost io_cost temp_space access_predicates filter_predicates projection time qblock_name other_xml varchar2(4000), varchar2(4000), varchar2(4000), varchar2(30), clob 3.3 Zbieranie statystyk 14